6 :
デフォルトの名無しさん :2005/11/03(木) 15:05:45
メッセージ通信がわからん 関数呼び出しが、同期なのに対比して、 同期・非同期よびだしどっちもできる ことをメッセージ通信っていって区別してんのかな
7 :
デフォルトの名無しさん :2005/11/03(木) 16:51:02
>>1 OS・言語・環境は問わないと言っているくせに
unix関連だけか?テンプレート書き直せ
ここのスレのひとは、どんなプログラム作ってるんですか?
糞スレ立てたり
12 :
デフォルトの名無しさん :2005/11/05(土) 02:06:21
【狂牛情報】アルツハイマーによる死者が50倍以上に アメリカ
159 - 衆 - 農林水産委員会 - 13号 平成16年04月27日 ○山田委員
エール大学神経病理学科外科部門の研究チームの検討を含め複数の研究で、剖検によりアルツハイマー病
あるいは痴呆症と診断されていた患者の三―一三%が実際はクロイツフェルト・ヤコブ病に罹患していた
ことが判明したとしている。米国では毎年アルツハイマー病と診断される患者が四百万人、痴呆症患者は
数十万人が発生していることから、最も少なく見積もって一万二千人以上のクロイツフェルト・ヤコブ病患者
が検出されず、公式統計に含まれない可能性がある。 注:12万人以上と思われる
実際、アルツハイマー病と診断された死亡患者数は一九七九年には八百五十七例であったものが、
二〇〇〇年には五十倍以上の五万例近くとなった。
159 - 衆 - 農林水産委員会 - 7号 平成16年03月18日 ○松木委員
記事の中に、アメリカでは、アルツハイマー病あるいは痴呆症と診断される人が年間四百万人いるそう
なんです。複数の研究機関の合同研究によると、このうち三から一三%が実際はヤコブ病であったことが
判明しております。少なく見積もっても十二万人はヤコブ病の公式統計に含まれていない可能性がある。
「アルツハイマーや若年性痴呆の中に変異型ヤコブ病患者が」・・米国牛輸入再開に京大医学部教授衝撃的指摘
http://news18.2ch.net/test/read.cgi/dqnplus/1120196765/ 【vCJD】牛海綿状脳症(BSE)と同じ病気“日本人発症しやすい”…厚労省研究班
http://news16.2ch.net/test/read.cgi/scienceplus/1088575874/l50
ちょっとばっかし知恵を借りたいのだが。 Linuxでとある画像フィルタリング処理を書いている取り引き先から、 マルチスレッド化して処理を高速化してくれと依頼がきている。 2CPUマシンで動かすから1CPUマシンでは動かなくてもいいらしい。 現状では、1枚の画像に対する処理にある程度時間がかかっていて、 それを複数枚処理してから先に進むロジックなのでその部分で 複数枚分のスレッドを起こせば2CPUに適当に分散できるのではないかと考えているらしい。 そこで相談。 ・2CPUマシンでマルチスレッド化はどの程度高速化が期待できるか。 #まさか理論どおり2倍になるなんて期待していないが。 ・マルチスレッドだとしたらどんな技術を使うことになるのか。 ・マルチスレッドではなくマルチプロセスでやるとしたらどうか。 マルチスレッド云々以前に、数千行のmain()をなんとかしてから高速化を検討しろといいたいのだが…… #あ、そのなんとかするのもこっちに依頼が来るらしいのだが、マルチスレッド化と抱き合わせなのがなんともはや。
>>13 > Linuxでとある画像フィルタリング処理を書いている取り引き先から、
この処理がCPUボトルネックなら、
> #まさか理論どおり2倍になるなんて期待していないが。
2倍近くになっても何の不思議もないが。
一般論としては、一枚をマルチスレッドで処理してもいいし、
一枚ごとにスレッド割り当ててもいいし。いずれにせよ簡単だろ?
15 :
13 :2005/11/07(月) 11:55:10
>>14 レスTHX。
>2倍近くになっても何の不思議もないが。
スレッド生成のボトルネックが気になるのだけど。
#プロセス生成よりは小さいのだろうけど。
man on wwwで調べてみた。
一枚の処理を分割するのは面倒なので、一枚ごとにスレッド分けるとして、
for (画面枚数分) {
pthread_create();
}
for (画面枚数分) {
pthread_join();
}
なんて安直なコードでもいいものかな?
#だとしたらmain()を分割した段階で半分以上仕事が終わったようなものなんだがw
>>15 まあいいんじゃねえ?
一枚ごと独立に処理出来るんでしょ?
画像がでかけりゃメモリの取り合いで遅くなる可能性もあるけど、
まあとにかくやってみればいいと思う。
# 数千行のmain()に画像処理が埋め込まれているわけね…
C#スレで質問していたのですがこちらのスレのほうが適切化と思ったので再度質問させていただきます。 たとえば次のような場合どうします? 株価などのように高頻度に値が更新されてそれに対する処理、その値を基にしたほかの株価データをを必要とする計算や表示などを行う必要がある。 値が更新されるー>対象となるデータノードを検索ー>それに対し値などに応じた必要な処理という流れ。 対象となるデータのノード数は10万単位。ただしすべてメモリ処理するものとする。 複数のノードにまたがる更新処理はない。 ノードの削除処理はない。 こんな場合どんなロックの粒度にしてどんなデータ構造にします? 自分の場合だとデータノードをインスタンスとしてそれをコレクションクラスにぶっこんであるとして、データノードにその変化に応じて処理するobserverが引っ付いている。 コレクションクラスをロックー>データノード検索ー>コレクションクラスのロック解除ー>ノードの必要な箇所にロック-> ノード内の関連データをその部分にロックかけながらアトミックにupdate-> 該当箇所のロックをはずしobserverに通知->各observerがおのおの独自の処理を行う。その際におのおの必要なロックをかける。 こんなんなんですが、皆さんはどんな風にされるんでしょう?
18 :
13 :2005/11/07(月) 13:52:40
>>16 >まあいいんじゃねえ?
うい、THX。
>一枚ごと独立に処理出来るんでしょ?
そそ、全画像処理後、集計してフィルタリングパラメータを変える繰り返し。
>画像がでかけりゃメモリの取り合いで遅くなる可能性もあるけど、
>まあとにかくやってみればいいと思う。
小さい小さい。最大128x128。
#なのに現状は2048x2048x16の実数値バッファがグローバルに固定で取られてて(512MB!)泣けます。
># 数千行のmain()に画像処理が埋め込まれているわけね…
そそ、あのパラメータを変えてフィルタリング、このパラメータを変えてフィルタリング、
って具合に同じ処理が繰り返し登場するのでその行数。
これをばらしてメモリを必要なだけ動的確保してやれば
1スレッド辺りのメモリ使用量も1MB程度に抑えられそう。
>>18 > 小さい小さい。最大128x128。
小さすぎてスレッド生成のオーバーヘッドが気になる時は、
スレッドプール使ってください。
20 :
13 :2005/11/07(月) 17:06:30
>>19 オーバーヘッドが大きいようならスレッド分割単位を見直すから多分問題にはならないと思うのだけど、
参考までにスレッドプールとは何か、ポインタを示してもらえませんか?
#ぐぐったけどWebアプリか.NetかC#かJavaの話題しか見つからなかった。
22 :
13 :2005/11/07(月) 18:12:55
>>21 THX。
一通り読んでみます。
#日本語で検索してたよ_/ ̄|○
23 :
デフォルトの名無しさん :2005/11/07(月) 19:30:54
>>13 ちょっと待てよ、お前。
さっきから聞いてりゃ言いたいことぬかしやがって。
飯食ってんだろ?できる見込みないものを依頼受けるなよヴォケ。
お前の相談は「丸投げ」なんだよ。ここは宿題片づけスレか?
気になるなら自分で実験したらいいべ?
24 :
13 :2005/11/07(月) 21:25:15
>>23 は、せっかくいいこと言っているのに、最後の
「いいべ」という田舎者丸出しの言い方で
説得力が無くなってしまった。
27 :
13 :2005/11/07(月) 22:22:05
取り敢えず>15に書いたような簡単なサンプルは作ってみましたが何か。 余りに単純すぎてスレッドが複数実行しているかどうか判らないような代物ですが。 水曜に客先の端末(2CPU)で分散処理するかどうかは見てくる積もり。 #あー、そもそも依頼を受けたかどうかは書いてない罠。
>>27 xosview動かして、1CPU版と比べたら、分かるかも〜
ランチャー作って二つプロセス起動させれば 全てOK。
YOU行ってみちゃいなよ。
// TEMPファイルを作成する関数の様なもの。このままスレッドで使うとバグる。 char * create_unique_file(char *file) { FILE *fp; if(NULL != (fp = fopen(file, "rb"))) { // 同名のファイルが既に存在する。 fclose(fp); // ※ここで違うファイル名を生成する処理を行う。 } else { // 同名のファイルが存在しないのでそのままのファイル名でファイルを作成する。 if(NULL != (fp = fopen(file, "wb"))) { // ここにきてほしい。 fclose(fp); return file; } else { // なぜかここにくる場合がある。errno:13(EACCES) } } return NULL; } // 上の関数をマルチスレッドで使うために若干のセーフティーを加えてみた。 void funk(char *file) { EnterCriticalSection(&cs); create_unique_file(file); Sleep(100);// これをコメントアウトするとバグる(時間が短いとバグりやすい?)。 LeaveCriticalSection(&cs); } // 上側の関数をマルチスレッドプログラム(HTTPDもどき)で使用していたところなぜかバグります。 // ・"wb"が失敗する。及び、プログラム全体のファイル送信がおかしくなる。 // 下側の関数のようにしたところ、 // ・Sleep(50〜)を入れると両方のバグが(見た目)出なくなる。 // fopen()が極短時間で重なっておかしくなっているのではないかと思っています。 // どうなんでしょうか・・・
>>33 排他していない版は、典型的なバグだね。
static int a;
static void foo()
{
while(a != 0){
}
// <-- (A)
a = 1;
// 処理
a = 0;
}
と同じ。
(A) の所で、スレッドが切り替わって同じルーチンが呼ば
れた時を考えればなぜバグっているかわかるはず。
ところで、排他制御を追加した版でも Sleep() がないと、
> // ・"wb"が失敗する。及び、プログラム全体のファイル
> 送信がおかしくなる。
の現象が出るの?
ちなみに、シングルスレッド用のライブラリをリンクしてるっ
てことはないよね。
>>33 > if(NULL != (fp = fopen(file, "wb"))) {
freopen()しろ、この呆けが!
37 :
33 :2005/11/12(土) 23:38:59
>>34 >>35 >>36 どうもです。
更に実行しまくってたらクリティカルセクション+Sleep()でもバグが出てます;;
>ちなみに、シングルスレッド用のライブラリをリンクしてるっ
>てことはないよね。
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <winsock2.h>
#include <stdio.h>
って感じでインクルードしてます(これらを用いて作成した関数群など)。外部のライブラリなどは使用していません。
"シングルスレッド用のライブラリ"を意識したことがないのですが、
"シングルスレッド用のライブラリ"ってことは<stdio.h>や<windows.h>のマルチスレッド用のがあるとかですか?
#define MULTI_THREAD// こんな感じの。
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <winsock2.h>
#include <stdio.h>
>>37 シングルスレッド・マルチスレッド用のライブラリの切り替えは、
VCならプロジェクトのプロパティの中のどこかにあるはず。
ただしここでいうライブラリはCランタイムライブラリのことなのでWinAPIは関係ない。
ファイル名を返すかわりに直接ハンドルでも返せば?
40 :
33 :2005/11/13(日) 00:04:52
>>36 読んでいます難しいです;
>>38 CLコマンドでコンパイルしているのですが/MTオプションを指定してみました。
ファイル送信のバグは今のところ目に付かなくなりました。
しかし"wb"のほうが激しくなりました。
ちなみにCとAPIのみで作成しています。
マルチスレッド用のライブラリについて調べてみようかと・・・
>>39 "rb"のかわりにGetFileAttributes()で判定するようにしてもだめでした。"wb"が開けないのはどうにも・・・
まさか、InitializeCriticalSectionしてないとか? あるいは、違うファイル名を生成する処理がおかしいとか。 あるいは、戻ってきたファイル名の扱いがヒドいとか。
>>40 > ちなみにCとAPIのみで作成しています。
へぇー fopen() と言う API がある OS もあるんだ…。
あと、
>>39 は、GetFileAttributes() なんかにつ
いて言ってるんじゃないと思う。
そもそも、ファイル名返してもそのファイルを書き込み
オープンする前に他のスレッドが書き込みオープンする
かもしれない。つまり、funk() から戻った時に既に
そのファイル名のファイルが作られてるかもしれないか
ら、ファイル名なんか返しても意味がない。
そうそう、普通に「そのまま使える物」を返すか 単に「呼ぶ度に違う名前を生成する関数」を作って、ファイルが開けなければ再試行するとか。 後者のものは、C標準にあるけどな。
44 :
33 :2005/11/13(日) 00:45:38
>>41 それは・・・ないとおもいますっ;><
>>42 vc++をインストールしているがコマンドラインでコンパイルしてて
MFCは使わずc言語標準関数とWin32APIで作ってます。
fopen()やfclose()を繰り返すのがまずいのかなと思い"rb"のfopen()を使わないようにしたのを作ってみましたが結果は同じでした。
"wb"がfopen()できないのにファイルポインタは返せないのでは?
初めのを閉じずに使用すれば次のもバグらなくなってウマーということでしょうか。
45 :
33 :2005/11/13(日) 01:02:38
とりあえず閉じずに返すようにしてみます。
>>44 すまん、
>>42 で大嘘書いてた。
fopen(〜, "wb") でファイルが作られるから、他のス
レッドがそのファイルを作ることはないはず。まあ、でも
わざわざファイル名を返して戻った先で再度オープンする
ならそのままファイルハンドルを返せばいいと思う。
そもそも、俺なら fopen(〜, "a") でファイルを開い
て、fgetpos() で取得したファイルポインタが 0 なら、
そのままそれを返すし、0 でなかったら違うファイル名で
再トライを繰り返すように作ると思う。
(他と衝突しない)ファイル名を作る
ファイルを書き込み+排他で作ってファイルポインタを返す
の一連の処理をクリティカルセクションでやるのはどうか.
>>42 の「そもそも〜」は合ってると思う.
>>33 の関数だとファイルを "wb" で作っても fclose ですぐ閉じる
ようになってるから.すでにあるファイルを "wb" で開くと
元のファイルは破壊される.
48 :
33 :2005/11/13(日) 03:30:42
TEMPファイルの作成は通し番号で作成するようにしたところバグがでなくなりました。 何とかいけそうです。 現在スレッドを作成するのにCreateThread()関数を使用しています。 調べているとCランタイム関数を使う場合CreateThread()はまずいようです。 以前から、rand()やsrand()を使っているプログラムでもCreateThread()を使っており謎のバグが発生しておりました。 とりあえず_beginthread()を使うように書き直してみます。 今は/MTオプションをつけなくてもコンパイルは通っています。 これが致命的だったのかもorz
なぜFILE*を返さないのかわからん。 OSが提供するロックのようなものなのに。 > これが致命的だったのかもorz _beginthreadexにするのは正しいが 33でやろうとしている内容であれば問題は起きない
50 :
>>46 :2005/11/13(日) 10:12:04
>>47 >
>>33 の関数だとファイルを "wb" で作っても
> fclose ですぐ閉じるようになってるから.すでに
> あるファイルを "wb" で開くと元のファイルは破
> 壊される.
いや、排他が入ってる版ならその前の
fopen(〜, "rb") のファイル存在チェックではね
られるから「すでにあるファイルを "wb" で開く」
ことはないはず。
>>48 > TEMPファイルの作成は通し番号で作成するように
> したところバグがでなくなりました。
おいおい、前はどうやってたんだよ…。
> 今は/MTオプションをつけなくてもコンパイルは通っ
> ています。
コンパイルが通れば OK なんて考えてるうちは、マルチ
スレッドプログラムなんか組まない方がいいと思う。
51 :
33 :2005/11/14(月) 08:02:54
TEMPファイルの作成は、 以前はtmp.txtが既に存在する場合はtmp(1).txtが存在する場合はtmp(2).txtみたいにしてました。 通し番号の方はtmp1.txt次はtmp2.txt次はtmp3.txtを問答無用に作成するようにしました。 _beginthread()を使用するようにしたところ、以前は謎のアクセスバイオレーションが発生していたのですが それ以前にどうみてもヌ○ポを踏んでいるようなエラーが出ます。 なんとなくSleep()でタイミングをずらしてみたところエラーが出なくなったりします。 マルチスレッドの場合、同じメモリ領域を同時に”読む”のもNGですか? if(NULL != *hoge)と*p = hoge;やi = hoge->num;が別スレッドで同時に起きるような場合もNGですか?
52 :
33 :2005/11/14(月) 08:08:11
踏んでいる場所を見つけようとチェックを埋め込んでみてもつかまりません。 自分で書いたコードよりも奥の方で発生しているようです・・・。
もはやマルチスレッド関係ないだろ。 初心者スレに行け。 create_unique_file()の稚拙なロジックが痛々しい。
54 :
33 :2005/11/14(月) 08:14:51
×if(NULL != *hoge) ○if(NULL != hoge) // hogeは構造体へのポインタです。 痛々しいロジックの方は忘れてください;><
>以前はtmp.txtが既に存在する場合はtmp(1).txtが存在する場合はtmp(2).txtみたいにしてました。 こんな文章しか書けないくらいだから、コードもとっ散らかってるんだろ。 小学校辺りから「頭の使い方」を勉強しなおしてみたら?
重複しないテンポラリファイルなんて、API使えば一発だろ。
>マルチスレッドの場合、同じメモリ領域を同時に”読む”のもNGですか? スレッド生成前にメモリ領域を確保して値しかいじらないのなら、同時に読んでもOK マルチプロセッサではメモリバリアを使って同期すればOK メモリ領域を複数スレッド内で確保と消去をくり返すような場合はリードライトロック。 > if(NULL != *hoge)と*p = hoge;やi = hoge->num;が別スレッドで同時に起きるような場合もNGですか? 別スレッドが *hoge ポインタの示す場所をいじるのなら、同期しないと全部アウト。
>マルチスレッドの場合、同じメモリ領域を同時に”読む”のもNGですか? intサイズだったらOKだよ。 前スレでそういう結論になった。
59 :
33 :2005/11/15(火) 05:26:59
/ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ | 作成された子スレッド内部で継続中flagを立てる前に | 親スレッドでflagチェック→終了判定→構造体NULLクリア | していたのがNULLを踏む原因でした。 \  ̄ ̄ ̄|/ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ∧_∧ / ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ( ・∀・) ∧ ∧ < おめーのバグだな、 ( ⊃ ) ( ゚Д゚) \____________  ̄ ̄ ̄ ̄ ̄ (つ_つ__  ̄ ̄ ̄日∇ ̄\| NullPo |\ ナントカナリソウデス  ̄ ======= \ イロイロトドウモアリガトウゴザイマシタ
親でflag立ててから呼べばいいじゃん。
61 :
デフォルトの名無しさん :2005/11/20(日) 03:06:17
windows には win32 API で色々なイベントを使えるようになってますが、 UNIXではpthreadのイベントを使う以外にないのでしょうか?
はぁ?
64 :
デフォルトの名無しさん :2005/11/20(日) 17:19:57
>>62 意味がわかんない。
自分が言ってる単語について全部調べてみたら?
わかんない言葉は使うもんじゃないよ。
65 :
デフォルトの名無しさん :2005/11/20(日) 17:29:22
セマフォをつかって、ある処理に関してロック、アンロックの処理が したい場合、ソースは以下のようなかんじ問題ないですか? ※以下のプログラムを2つ同時に動かした場合、 セマフォの開放は1つ目のプロセスによって行われているので、 2つ目のプロセスはIPC_RMIDの際に、エラーが出てしまいますよね。 これって、基本的にはどうするといいんですかね?
66 :
65 :2005/11/20(日) 17:29:42
#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/types.h> #include <sys/sem.h> union semun { int val; struct semid_ds *buf; unsigned short int *array; struct seminfo *__buf; }; int lock(int argc, char *argv[]) { union semun semaphore_union; struct sembuf semaphore_buffer; int semaphore_id; semaphore_id = semget((key_t)1000, 1, 0666 | IPC_CREAT); semaphore_union.val=1; //sem init if ( semctl(semaphore_id, 0, SETVAL, semaphore_union) != 0 ) { exit(1); } //lock semaphore_buffer.sem_num = 0; semaphore_buffer.sem_op = -1; semaphore_buffer.sem_flg = SEM_UNDO; if ( semop(semaphore_id, &semaphore_buffer, 1) == -1 ) { exit(1); } sleep(30) // 何かの処理の変わり //unlock semaphore_buffer.sem_num = 0; semaphore_buffer.sem_op = -1; semaphore_buffer.sem_flg = SEM_UNDO; if ( semop(semaphore_id, &semaphore_buffer, 1) == -1 ) { exit(1); } //sem end if ( semctl(semaphore_id, 0, IPC_RMID, semaphore_union) != 0 ) { exit(1); } return(0); }
67 :
65 :2005/11/20(日) 17:30:42
//sem end if ( semctl(semaphore_id, 0, IPC_RMID, semaphore_union) != 0 ) { exit(1); } この際に、一つめのプロセスが既に削除しているので、 2つ目のプロセスでは、エラーが帰ってきてしまいます。 基本的にセマフォの扱いって、どう記述するものなんですか。
68 :
65 :2005/11/20(日) 17:31:19
正しいやり方かはわからないが。 @プロセス1の処理が終わったら、セマフォに「プロセス1終わったよ」書き込む。 A「プロセス1終わったよ」になるまで待機してから、 「プロセス2も終わったよ」を書き込んでから、プロセス2を削除。 B「プロセス2も終わったよ」を確認してから、プロセス1を削除
69 :
65 :2005/11/20(日) 17:31:49
>>68 それぞれのプロセスをIPC_RMIDさせる直前までwait させろってことですよね。
そのケースは、事前に立ち上がるプロセス数(たとえば、自分で
fork して作成したプロセス)が分かっている場合、有効ですよね。
何個のプロセスがあがるか分からないときの手段としては、
IPC_RMID させる時は、手動で打つがいいのかな。
70 :
デフォルトの名無しさん :2005/11/20(日) 17:35:42
>>65 ここはマルチ「スレッド」のスレだ。
決してマルチ「プロセス」のスレではない。
マルチプロセスプロ倉羅民具スレなんてねーんだから ここでいいじゃん
いや、素直にUnixプログラミングスレかUnix板に行くべきだろう。
73 :
デフォルトの名無しさん :2005/11/20(日) 23:03:49
shared libを作ろうとしてまして、 その中でスレッドを起動して使いたいのでつが、 問題ないでしょうか?
>69 親が代表してセマフォを造って、削除する。 子供は親の造ったセマフォをみて触るだけ(無ければエラーにする)とか。 セマフォを開いてみて、無ければ造る。 造る時に排他制御して、唯一造れた人が責任をもって廃棄する、とか。
75 :
65 :2005/11/21(月) 00:29:05
>>70 >>72 Unixプログラミングすれから、誘導されたんですよ。
>>74 実務レベルだと、
親=オペレータが、起動スクリプト(セマフォ作成)をたたく。
サーバー終了時に、終了スクリプトをたたく。
オペレータ介さないと考えると、init.dに、SXXXXスクリプト)を作成し、
runレベルに合わせて、起動、終了のシンボリックリンクをはる。
なんて感じですかね。
>>75 そりゃ気の毒に、誘導が間違ってる。無責任にこの辺に誘導しとくよ。
「VIPPERでもわかるプログラミング」
>>73 過去の経験から言わせてもらうとライブラリ側で勝手にスレッドを起動するような
作りはあらゆる意味で良くない。
どうしても必要ならばまずそのスレッドで起こりえる可能性をすべて列挙してみる。
スレッドが起動するという事、その際例外が発生した場合どういう処置がなされるべきか、など。
判断がつかなければコールバック等でそのスレッドのトップレベルループや
ドメインに該当する処理に対してユーザーが干渉できるようにしたほうがいい。
↑domain
|user_thunk_procedure
|thread_callback
これらをドキュメント等も含めきちんと導出できないと第三者にはまず提供できない
代物になる。もしくは欠陥を持ったライブラリが完成する。
78 :
デフォルトの名無しさん :2005/11/22(火) 00:23:28
マルチスレッドの例外処理ってどうやってまつか、みなさん。
大域くくって落ちたらやりなおし、 ループでもなんでも、気をとりなおして次の処理。
80 :
73 :2005/11/22(火) 01:45:30
>>77 ありがとうございますた、
厳しいみたいでつね、もっと勉強しまつ。
winapiスレと迷いましたが、_beginthreadex()に関して質問があります。 現在_beginthreadex(NULL, 0, .....); としてメモリ割り当てを特に指定していません。 現在は実験のためにあるスレッドをいくつも作りたいのですが、 そうすると、エラーが起こりその原因の場所を調べると #endif /* _WIN64 */ return HeapAlloc(_crtheap, 0, size); という箇所でした。毎回ここでエラーが出ているようです。 この原因としてスタック領域のメモリ不足だと自分では思っているのですが、 実際のところはどうなのでしょうか? また何かいい解決方法を教えていただけないでしょうか? 現在は数十スレですが、将来的には数百スレを扱いたいと考えています。
いいえ、その情報だけですとスタックではなくヒープの確保が失敗したと思われます。 マルチスレッド云々以前に初心者歓迎スレ辺りでソースを晒してみては如何でしょう。
スレッドが多すぎてヒープ(のアドレス空間)が足りなくなるという可能性も無くはないけど 数十スレッド程度でそんなことになる筈もなく そもそもスタック領域がヒープを圧迫するかどうかという問題も
84 :
81 :2005/11/28(月) 10:47:04
舌足らずですいません。 エラーが起こるのは_beginthreadex()内の処理のようです。 _beginthreadex()を呼び出して目的のスレッドを作成しようとすると その過程の最中で81のようなエラーが出現してしまいます。 あと、 「メモリがreadになることはありませんでした。」 というメッセージボックスが表示されるのですが 何か関係あるのでしょうか? スレッド数は32、64、96と増やしていきたいのですが 32の段階でのエラーです。
だから、マルチスレッド以前のレベルでバグってるんだろってば。 自分のソースも追えないような蛸なら初心者スレでソース晒せって。
> あと、 > 「メモリがreadになることはありませんでした。」 > というメッセージボックスが表示されるのですが 自分で確保したメモリ領域外のアドレスを読みに行ったときに出る.
エスパーの俺様が、スレ違いのバグを解決してやろう。 malloc系を呼び出したときにライブラリ内でエラーが起こるのは ヒープの管理ブロックが壊れている時だ。 つまり、mallocした領域以外をfreeしたり、同じ領域を2度freeしたり あるいは確保した領域をはみ出して書き込みをした場合に起こる。
88 :
81 :2005/11/28(月) 22:43:36
すいませんでした >87さんのレスを手がかりにmalloc(), free()を中心に調べていったところ p = (int *)malloc(sizeof(short) * num); という箇所がありました。 sizeof(int)に直したところ変なエラーはでなくなりました。 心配されていた方々申し訳ございませんでした。
だから>82や>85がマルチスレッド以前のバグだって指摘してたのに……
うるせえ黙れ
>>88 心配してねーよ。
こいつ馬鹿だなと思っていただけ。
>>88 誰も心配はしてないとおもいます。アドバイスしてただけ。
日常でもそのような勘違いをしているとなぜあの人は自分のことしか考えないのかと思われるので注意しましょう
93 :
愛也 :2005/11/29(火) 15:57:01
質問なんですが・・・・どなたか教えていただけないでしょうか? (1) 特定のデータを指定するにはアドレス信号を用いる。どれだけのアドレス信号が発行できるかはアドレスバスの本数による。 アドレスバスの本数が8本のときは( 1 )個、12本の時は( 2 )個のアドレスを発行する事ができる。 (2) 容量32KBのメモリがある、このメモリにバイト単位でアドレスをつけた場合(アドレス幅は8ビット)、全アドレスを指定するには、最低( 3 )本のアドレスバスが必要である。 同時に256MBの場合は( 4 )本必要である。 上の問題をどなたかお時間がある方がいらっしゃれば教えていただけないでしょうかぁ?? 何卒よろしくお願い致します。
>>93 そのうえ問題自体に間違いがある(w
コピペミスかもしれんが(w
HTマシンでpause命令使って効果実感した人いる?
メール欄が空ですよ
93は、 スレ題名に「マルチスレッドプログラミング相談室」と書いてあるから、 「ここはマ板共用の相談スレに違いない!」と思ったんじゃないの?
マ板?
Windows でマルチスレッドを実現するには CreateThread API 以外に方法はありますでしょうか?
_beginthread
つうか何がしたいんだ
いろんな恋がしたい
マルチフ恋奴
ほしょ
>>104 マルチスレッドな恋なんかしてると火吹くぞ
俺のセマフォは3カウントまで。
109 :
デフォルトの名無しさん :2005/12/14(水) 00:13:25
セマフォなんてニッチで泥臭いものは今日日使わないよ
オレのMutexは一度もLockされたことがない…orz
そこはまさにCriticalSectionなので、触れてはいけない。
一生一WorkerThread。
オレのFutureはいつまでたっても実体を返さない…orz
オレのQueueはいつも空っぽ…orz
Terminateされたい性分なんです、スレッド失格でしょうか?
だれかJoinしてクレー!
117 :
デフォルトの名無しさん :2005/12/14(水) 01:10:22
オレのQueue、気付いたときにはStackになってた
118 :
デフォルトの名無しさん :2005/12/14(水) 01:41:29
恋はいつも非同期(asyncronous)
クリスマスなのにDaemonです…orz
僕の人生Suspendしています。誰が解除してくれるんですか?
俺はreturnしちゃったよ
signal投げてくれる筈のプロセスがゾンビになっていた件について
それマルチスレッドじゃねーし
彼女といつも同期に失敗しまつ
俺はいつもシングルスレッド。
漏れのセフレはヂュアルコアだから2穴使って楽しめるよ。
おまいら、そろそろ戻ってこい
goto 107
mutex と spin lock の使い分けの基準て何?
使い分けってお前
mutex: 居間のテレビのチャンネル権取得に使う spin lock: 朝、トイレの空きを待つ時に使う
後者、spin lockになるのはガマン出来ないときに限られると思われ
スピンロックって、カーネルモードへの移行よりも短い時間しかブロックされない処理、 例えば単純な変数の読み書きなんかに積極的に使いたくなるのだけれど シングルプロセッサのシステムで、 ロックしているときにコンテキストスイッチが起きて 別スレッドがロック取得しようとすると すげー時間が無駄になるんだよね。 それがちょっと嫌。
134 :
デフォルトの名無しさん :2005/12/17(土) 20:56:42
>>133 知ったかはよくないぞ。入社2年目のおぬし。天狗の鼻をへし折られろ。
我が社では、spin lock の事を フレンドリーに「ぐるぐるくん」と呼んでいる。
我が社では回転元彌チョップと呼んでいる。
137 :
129 :2005/12/17(土) 22:48:09
>>131 よくわからんです
>>133 その単純な変数の読み書き以外に、どうしても spin lock を使い
たいんじゃ! とか、spin lock じゃないとうまくいかないような、
典型的なケースってないすか?
>>134 じゃあ、どこがおかしいのか指摘しろよ。
業界最底辺を何年も続けてる事だけが自慢の
低脳プログラマさんよ。
マルチプロセッサでも、
ロックを取得している状態で実行権を奪われたら起こりうるのは確かだけどな。
140 :
デフォルトの名無しさん :2005/12/18(日) 01:43:49
>>138 お前の存在そのものがおかしいことを指摘してやらんでもない。
141 :
デフォルトの名無しさん :2005/12/18(日) 01:46:16
指摘してほしいのに しろよ はないだろ。 せめて、「わたくしは無知なので、できれば、ご指摘いただけないでしょうか?」だろ。 誠心誠意で言葉に気をつけろ。
ナニこいつ
具体的に指摘しないのは荒らしと同じだから放置汁
チョンはすぐにファビョるからやあねえ。
145 :
デフォルトの名無しさん :2005/12/18(日) 18:57:20
Win32(XP)で下のような排他制御を考えないプログラムを書いて 実際にハングするところを確かめたかったのですが、何度実行しても上手くハングしてくれません たまたま運が良くてハングしなかっただけなのでしょうか?ご教示願います #include <stdio.h> #include <windows.h> #include <process.h> unsigned __stdcall mythread(LPVOID); int main(){ unsigned int thID; HANDLE hTh = (HANDLE)_beginthreadex(NULL, 0, mythread, NULL, 0, &thID); for (int i = 1; i <= 100; i++) { FILE *fp = fopen("test.txt", "a"); fprintf(fp, "Main---%d\n", i); fclose(fp); } WaitForSingleObject(hTh, INFINITE); CloseHandle(hTh); return 0; } unsigned __stdcall mythread(LPVOID lpx) { for (int i = 1; i <= 100; i++) { FILE *fp = fopen("test.txt", "a"); fprintf(fp, "Thread---%d\n", i); fclose(fp); } return 0; }
この程度でハングはしないと思うが、 同期とらない=ファイルの中身はグチャグチャになるの? って意味ならば出力されたファイルを読め。
147 :
デフォルトの名無しさん :2005/12/18(日) 19:38:13
>>146 ファイルもぐちゃぐちゃになりません。きちんと出力されます
また、一度に書き込む文字列のサイズを100KB程度と大きくしてもきちんとと出力されます
しかし、どちらかのスレッドにSleep(0)等を入れる程度でぐちゃぐちゃになります
境界はどこに有るのでしょうか?
ヒント:ストリーム系はバッファリングされるから混ざりにくい。
fprintf-fcloseの間にスレッドが切り替わらなければセーフ。 んで、100回くらいのループではWindowsのタイムスライスに 引っかからなかったりするのでは。 マルチプロセッサなら、カナリヒドい事になりそうな気がするのだけれど。
>>149 > fprintf-fcloseの間にスレッドが切り替わらなければセーフ。
そうとは限らない。
>>148 「一度に書き込む」っていってんだから、
バファリングの有無は関係ないような気がするんだけど。
そもそもハングするのか? ハングはしないだろ
153 :
145 :2005/12/20(火) 01:28:57
いろいろ調べてましたが
IO絡みの関数は基本的にスレッドセーフに作られてるから
ってのが答えみたいです
お騒がせしました
>>149 それは違います。たとえfcloseをコメントアウトしてもハングしません
>>152 ハングはしないようですね
このページに「大抵ハングしてしまいます」と書かれていて気になったのです
http://www.kumei.ne.jp/c_lang/intro2/no_106.htm まあこのページに限らずネット上でマルチスレッドを初心者向けに教えているサイトでは
大抵同じような書かれ方がされてるので、
もしかすると私の検証が不十分なのかもしれませんが・・・
同時に書き込んで壊れなくても 後からの書き込みで前の書き込みは上書きされて消える訳だが
>>153 ランタイムライブラリがスレッドセーフで無い場合はハングするかもしれないけど、
VS2005からシングルスレッドのランタイムは無くなっているなあ。
「ハングする」なんて言い方は止めて、 「動作が未定義」くらいにしてくれないか。 本当にハングアップするかどうかを問題にしているんじゃないだろ?
157 :
デフォルトの名無しさん :2005/12/25(日) 13:24:46
/MT ってやってればたいがい大丈夫だろうけど、スレッドセーフでない関数で gethostbynameとかが未定の動作されるとかなり困る、 無理矢理排他同期とって使ってるけどなんかかっこ悪い。
winsockのgethostbynameはスレッドセーフじゃなかったっけ?
明記してあるな。 >Remarks >The gethostbyname function returns a pointer to a hostent structure-a structure allocated by >Windows Sockets. The hostent structure contains the results of a successful search for the >host specified in the name parameter. >The application must never attempt to modify this structure or to free any of its components. >Furthermore, only one copy of this structure is allocated per thread, so the application should ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ > copy any information it needs before issuing any other Windows Sockets function calls.
struct hostent *host; host = gethostbyname(argv[1]); ってな形だし、どうみてもスレッドセーフでないと思ってた。 スレッド固有メモリなんてものでも使ってるのかな。
>>161 それだけでMT-Safeだとは限らない。
getaddrinfo ってのがあるんだ、 参考にしてた本が古っかったので知らなんだ。 該当箇所を書きかえねば orz
2ちゃんで書き込みするときの文字2048制限解除方法誰か教えてください。
制限解除して書き込んでる人が増えてるんですが
>>164 古いWindowsではありませんのでその辺は配慮を。
「スレッドできる」と「スレッドでファイル操作しても問題ない」は同義じゃないよなあ。 単一リソース操作は対策しないと普通は競合するよ。
マルチスレッドなサーバプログラムを作ってみようかと思ってます クライアント数が少ない場合1クライアントに1スレッドを割り当てればいいかなと思いますが クライアント数が多い場合はどういった方法が良いんでしょうか? 1スレッドあたりのクライアント数を決めてスレッドごとにselect()するとか 親スレッドでselect()して処理を別スレッドに任せるとか一応考えてはみていますが どういった方法がスタンダードなんですかね?
ジョブキュー
+スレッドプール
裏技としてApache 勉強にはならんな・・・
apacheって何言ってんの? ネットワークプログラミング相談室にも沸いたバカだろか。
なぜそこで、あと半歩踏み込んで「apache馬鹿よね〜」とか言えないよねぇ
おバカSunよね〜
くだらない質問ですみませんが TCPで同じディスクリプタにread()するスレッドとwrite()するスレッドを分けたとき 全二重だから同時にread()とwrite()を実行しても問題ありませんよね? あと片方が同期無しでclose()するのって問題ありますかね
同時にread/writeしても問題なし。 HTTPサーバのようなものを作ってるなら相手が一方的にclosesocketしたくらいでおかしくなっては困る。
Solaris2.xではデッドロックしてたなあ(遠い目)
x86 とかで int の値を書き込むスレッド(A)と読み込むスレッド(B)がある場合, 更新途中の値が(つまり 32bit 中の 16 bit が新しい値で残りが古いままとか) B に見えてしまうということはありうるでしょうか? # long とかだとまずいですよね.
>>179 前スレで延々やってたと思う
そこが本題でなければ、排他で済ませて先行った方がいいと思うヨ
>>180 レスありがとうございます.前スレの読み方がよく分からないので憶測になっ
てしまいますが,前スレの議論では結局「あり得る」という結論に至ったとの
理解で良いでしょうか?
参考になりそうな資料へのポインタを教えて頂けるとうれしいです.
> そこが本題でなければ、排他で済ませて先行った方がいいと思うヨ
性能的な面から可能な限り B に対する排他処理は避けたいと考えています.
>>181 OSに用意されている、Atomicな書き換えAPIを利用すれば宜しかろう。
32ビットバスでアライメントも合っていれば素直にAtomicに書き換わると思うが。
レスありがとうございます。調べてみます.
184 :
デフォルトの名無しさん :2006/01/13(金) 02:07:27
マルチスレッドプログラミングで注意することを列挙してくれ。
ひとつ!急いで口で吸え!
ふたつ! 不埓な悪行三昧!
みっつ! 想定の範囲内です。
よっつ、読んでも書いちゃダメ
いつつ、いつも心に排他処理
むっつ、無理せずmutex
ななつ、仲良くSemaphoeで共有
やっつ、やっぱりここでも排他処理
ここのつ!心を鬼にして排他処理
糞スレ立てんな
とう、でとうとう割り込まれた。 排他だけじゃなく、割り込み禁止も忘れないでね☆
HANDLE hEvent = CreateEvent(NULL, TRUE, FALSE, NULL)で作ったイベントに対して SetEvent(hEvent);←TRUEがかえる でも、その次に WaitForSingleObject(hEvent, 0)とやってもWAIT_OBJECT_TIMEOUTがかえる。 こういうことがおきているのですがどのようなことが考えられますか?
>>196 SetEventは成功したけど、イベントオブジェクトがシグナル状態になる前にWaitForSingleObjectがタイムアウトした。
>>196 他のスレッドが一生懸命 ResetEvent(hEvent) を
やってる。
199 :
196 :2006/01/21(土) 14:20:25
>>197 SetEventってシグナル状態にした後で戻るわけではないのですか?
>>198 ソースを見る限りほかのスレッドが触ることはなさそうなのですが確信持てないです。
SetEventとWaitForSingleObjectの間で他のスレッドにスイッチしなければそういうことはおきないですよね?
であれば確認のためにはスレッドのスイッチをSetEventとWaitForの間で抑制してあげればいいですよね。
なにか、任意のコードブロックではスレッドスイッチを禁止する方法はないでしょうか
ちょっと確認だが、WaitForSingleObject()の第二パラメータの0ってNoWaitだよな? 単に待てば委員で内科医?
>196のままのコードを実行してみたけど、ちゃんと0が帰ってきたよ。
>>199 >>196 の事象が事実であるなら、そういうものだと思って使うべき。
嫌なら別の手段を用いるべき。
203 :
196 :2006/01/21(土) 15:47:24
>>200 SetEventしてそれが本当にシグナルになったかを見るためにWaifFor・・したのですが、
それがなぜかシグナルになっていないのです。
>>201 検証ありがとうございます。
>>196 のままのコードだとそうなると思いますが、実際にはほかのスレッドもいるので
何が起きているかはよくわかっていません。(デバッガでステップ実行したりデバッグライトを入れるだけで動きが変わるため)
とりあえず、月曜にほかのスレッドがResetしていないか確認したいと思います
あとSetEventって非同期に動いたりしませんよね?
SetEvent(hEvent);
ここで誰かがResetEventしない限り下はTRUEにならないですよね?
if(WaitForSingleObject(hEvent,0)==WAIT_OBJECT_TIMEOUT)
{
}
>>203 だから、WaitForSingleObject(hEvent, INFINITE)してみたら?
そもそも、WAIT_OBJECT_TIMEOUTってなんだ? 成功:WAIT_OBJECT_0 or WAIT_TIMEOUT or WAIT_ABANDONED 失敗:WAIT_FAILED のいずれかが、WaitForSingleObject()の戻り値なんだが・・・ とりあえず、該当部分のコードを晒せ、晒したくなかったらコピペも満足にできない房は二度とくんな。
>>199 > ソースを見る限りほかのスレッドが触ることはなさそ
> うなのですが確信持てないです。
はぁ? 悪いけど、変数がどっからアクセスされるか自信
が持てないなんて言う奴にはマルチスレッドプログラムは
無理だよ。あきらめたら?
>>203 で、デバッガとか言ってるが君がやることは、デ
バッガでプログラムを追っかけることではなく hEvent
で全ソースに対して findstr することだと思う。
(そこらじゅうで hEvent 使ってるなら、問題のところ
の変数名を変えるべき。)
>>201 うちでも、CreateEvent() 〜 SetEvent() 〜
WaitForSingleObject() 〜 CloseHandle() を
10,000,000 回実行したが、WAIT_OBJECT_0 しか
返らないよ。
>>202 その考え方はおかしいだろ。
>>196 みたいな動きをするイベントなんて使い物にな
らないと思う。
>>206 >
>>196 みたいな動きをするイベントなんて使い物にな
>らないと思う。
eventは許可するまで待たせておくことが目的の物だから、setは少しくらい遅れても良いと思う。
acquireI->releaseする同期モノのreleaseも同じ。
>>207 少しってどれぐらい?
1秒なの? 1ms なの? 1μs なの?
他のスレッドに対して set の伝播が遅れるのは問題ない
けど、自スレッドに対して SetEvent() してからイベン
トがセットされるまでの間に「隙間」があるのは問題。
例えば、
SetEvent(hEvent); // hEvent は、ワーカースレッドか処理終了でセットする。
StartWorkerThread(); // 処理開始指示。
while(WaitForSingleObject(hEvent, 0) == WAIT_TIMEOUT){ // 終了したか?
// 終了してないなら、他のことしてようっと。
}
(こんなプログラムは組むなと言う意見はまた別の機会に。)
と言うプログラムがうまく動かない。
動かないだけなら、まだしも下手するとうまく動いたり動
かなくなったりすると言う最悪パターンになる。
マルチスレッドプログラムやるなら「隙間」をもっと意識
できないとはまるよ。
>自スレッドに対して SetEvent() してからイベン >トがセットされるまでの間に「隙間」があるのは問題。 いやだから、その隙間は無いんだって。 というか、先頭のSetEventはResetEventの間違いだよな、な。
>>208 次にタスクスイッチが起こったときにsetしてくれればいい程度に思って使ってるね、私は。
>while(WaitForSingleObject(hEvent, 0) == WAIT_TIMEOUT){ // 終了したか?
普通スレッド終了の検知はスレッドのハンドルをWaitForSingleObjectの引数にする。
わざわざeventなんて作らない。
スレッドをプールするなんて言い訳は聞かない。
>>211 面倒なことはOSに任せて今まで通りにやる。
>>210 すまん、勘違いだ。
セット側はさすがにちょっと考えにくいな。
(まあ、リセット側も無理矢理だが。)
ただ、セット側とリセット側で挙動が違うのはちょっと気
持ち悪い。
>>211 マルチコアって言ったって、マルチプロセサの一形態だろ。
別に何か変えないといけないのか?
専用のチューニングが必要になったらそのとき勉強するよ。
>>212 > 普通スレッド終了の検知はスレッドのハンドルを
> WaitForSingleObjectの引数にする。
スレッドの終了 ≠ 処理の終了
誰も、スレッドの終了の検知方法なんて聞いてないぞ。
最近知ったので、知ったかしたくなったのか?
さーしったかしったかたーこうりんだー さーしったかしったかたーこうりんだー みぎあしくんひだりあしくん
>>214 気が済んだか?
すっきりしたら、違うスレに行ってくれよな。
>>213 >スレッドの終了 ≠ 処理の終了
そういうことを言いたかったのか。
VC6.0でスレッドを生成するために、 _beginthreadexを使おうと思っていますが、 1プロセスあたりに生成できるスレッド数って 決まっているのでしょうか? MSDNのCreateThreadのヘルプには、 2028との数字がありますが・・・
スタック用のメモリ領域が1MB確保されるんじゃなかったかな
そんなにスレッド作ってどうするの?
特殊用途か設計ミスか勘違い
>>217-220 まさに、その「設計ミス」(要は、バグ) で、
スレッド作りすぎてアプリケーションエラー
出しまくった俺が来ましたよ。
うちの環境だと、1600個位でおかしくなった。
ただスレッドを生成するのが、メーカー提供の
COM の中なので、生成する時にどんなエラー
が返ってきているかはよくわからん。
なんじゃそりゃ(´・ω・`)
>>196 例えば
1.CreateEvent の第2引数が FALSE(自動リセットオブジェクト)である
2.スレッドAが WaitForSingleObject(hEvent, INFINITE) している
3.スレッドBが SetEvent(hEvent) を呼び出す
4.スレッドAが待機状態から解放される
5.スレッドBが WaitForSingleObject(hEvent, 0) を呼び出す
こういう場合、他のスレッドが ResetEvent しなくても 5.は WAIT_TIMEOUT
を返すけど、CreateEvent の第2引数が TRUE なら WAIT_TIMEOUT を返すのは
おかしいね。
WAIT_OBJECT_TIMEOUT って書いてたことがばれて逃げてったやつに追い討ちかけんなよ。
A.EXE と B.DLL があり、B.DLL が foo() という関数をエクスポートしており、 foo() は内部的に strtok 等の C ランタイム関数を呼ぶとする。 B.DLL 内部で _beginthread(ex) したスレッドの中で foo() を呼ぶのは当然問題 ないはずだけど、A.EXE が内部で CreateThread または _beginthread(ex) した スレッドの中で B.DLL の foo() 関数を呼び出した場合、メモリリークするの? B.DLL が DLL_THREAD_ATTACH/DETACH できちんとスレッドごとの初期化・後始末 をしていれば大丈夫そうな気がするんだけど、VC とか BC とかの C ランタイム ライブラリはこの辺どうなってるんだろう。
228 :
225 :2006/01/27(金) 23:32:29
>>227 > B.DLL内部で_beginthread(ex)したスレッドからA.EXE中の関数bar()を呼ぶとリークする。
コールバック関数とかも、そのコールバック関数が自EXE で _beginthread(ex)
したスレッドから呼ばれないなら C ランタイムを使えないことになりますね。
>>227 の質問を繰り返すことになりますが、A.EXE 内部で _beginthread(ex) した
スレッドから B.DLL 中の関数 foo() を呼ぶのは大丈夫なんでしょうか。
DllMain の DLL_THREAD_ATTACH/DETACH はこのへんの問題を解決するための
機構だと思ってるので、きっと大丈夫なんだと自分に言い聞かせるようにし
てるんですが…。
229 :
225 :2006/01/27(金) 23:34:18
>>227 > CRTはソース公開されてるから気になるなら読むといいよ。
VC6 のソースを見る限りでは、DLL_THREAD_ATTACH/DETACH でスレッドごとの
初期化/後始末をしているようです。
CRT を使う DLL に関して、VC6 のソースを見た感じでは、その DLL が
C ランタイムをスタティックリンクしている場合は _DllMainCRTStartup 内で
DllMain を呼ぶ前に DisableThreadLibraryCalls を呼ばないようです。
MSVCRT.DLL を使用する場合は、ユーザー定義の DllMain がない場合のみ、
DisableThreadLibraryCalls を呼んでいるようです。DllMain があった場合、
DllMain 内部で DLL_THREAD_ATTACH/DETACH が必要になる可能性があるから
DisableThreadLibraryCalls を呼ばないようにしてるのでしょう。おそらく。
だから、EXE 側で作成したスレッド内で、DLL 側の C ランタイム関数を使う
関数を呼び出しても、DLL_THREAD_DETACH で後始末が行われるのでメモリリーク
は発生しないのではないかと思ってますが、それが明記されているドキュメント
が見当たらないので気になっています。
230 :
225 :2006/01/27(金) 23:36:13
実際のところってもなあ hackして怪我するのってあほらしくないか
>>230 Cランタイム関数はスレッドなんてのが出来るまえのシロモノだからね。
漏れの知る限りでは、
リンクしてるCランタイムライブラリが同じでマルチスレッド対応なら、
EXEとDLLで相互に呼び合いとかしても別段問題ない。
なぜなら、Cランタイムが使う領域は_beginthread*()でスレッド生成時に
スレッドローカルに確保されて、そちらが使用されるから。
(→see AdvancedWindows)
ただし、_*thread*()はランタイムライブラリに含まれる関数だから、
異なるライブラリを混在すると問題になる場合がある。
MS libcmtとMSVCRTの混在も危険。
(→see MSDNの/MDあたりのオプションのヘルプ)
234 :
225 :2006/01/28(土) 14:56:16
ちょっと試してみました。 B.DLL void foo(void) { char dummy[256]; strtok(dummy, ""); } A.EXE DWORD WINAPI ThreadProc(void *pvParam) { foo();//B.DLL 内の関数 return 0; } void test(void) { HANDLE hThread; DWORD dwThreadId; int i; for(i = 0; i < 10000; i++){ hThread = (HANDLE)CreateThread(NULL, 0, ThreadProc, 0, 0, &dwThreadId); WaitForSingleObject(hThread, INFINITE); CloseHandle(hThread); } }
235 :
225 :2006/01/28(土) 14:57:27
>>234 の続き
1.A.EXE: BCB5 で作成、B.DLL: VC6 libcmt.lib で作成
2.A.EXE: BCB5 で作成、B.DLL: VC6 msvcrt.lib で作成
3.A.EXE: BCB5 で作成、B.DLL: BCB5 で作成
結果:
1:DllMain で DisableThreadLibraryCalls を呼ぶとメモリリークする
(test を呼ぶ度にメモリ使用量が増える)
DllMain で DisableThreadLibraryCalls を呼ばなければメモリリークしない
(test を何回呼んでもメモリ使用量は変わらない)
2:DllMain で DisableThreadLibraryCalls を呼んでも呼ばなくてもメモリリークしない
3:DllMain で DisableThreadLibraryCalls を呼んでも呼ばなくてもメモリリークする
ちなみに
void foo(void)
{
char* dummy = (char*)malloc(128);// char *dummy = new char[128];
free(dummy);// delete[] dummy;
}
の場合、どの場合においてもメモリリークしない
236 :
225 :2006/01/28(土) 14:59:56
>>235 の続き
結論:
BCB5/VC6 で作成した B.DLL においては、C ランタイムルーチンのうち、少なくとも
malloc/free/new/delete しか使わない分には、A.EXE で作成したスレッド内で B.DLL
の関数を呼び出してもメモリリークしない。スレッドの作成に _beginthread(ex) を
使う必要もない。
VC6 で MSVCRT.DLL とリンクする B.DLL では、A.EXE で作成したスレッド内で B.DLL
の関数(内部で C ランタイム関数を呼ぶもの)を呼び出してもメモリリークしない。
VC6 で libcmt.lib とスタティックリンクする B.DLL では、DllMain で
DisableThreadLibraryCalls() を呼ばなければ、A.EXE で作成したスレッド内で
B.DLL の関数(内部で C ランタイム関数を呼ぶもの)を呼び出してもメモリリーク
しないが、DisableThreadLibraryCalls()を呼ぶと、B.DLL が内部で呼び出している
C ランタイムルーチンによってはメモリリークする可能性がある。
他にも色んな組み合わせが考えられますが、とりあえず自分が知りたかった
「A.EXE で作成したスレッド内で B.DLL 内の関数を呼び出してもメモリリーク
しないのか」は検証出来ました。この程度の実験で検証出来たと断言して良い
のかはわかりませんが。
BCB5 の C ランタイムルーチンは DLL_THREAD_ATTACH/DETACH をきちんと処理して
いないものと思われます。BCB5 で作った DLL はマルチスレッドアプリケーション
からは使いにくいですね。
VC7 以降とか GCC とかではどうなんでしょうね。
検証の仕方が間違ってたらご指摘下さい。
>>236 率直に言えば無意味な検証。
というのは、メモリリークだけが問題ではないから。
仮にメモリリークしていなかったとしても、
複数のスレッドで同時に1つのワークエリアを参照していれば、
各スレッドがお互いに1つのワークエリアをぶっ壊しあう。
喪前さんのやり方では、そのパターンが検出できない。
むしろ、メモリリークしている方が複数のスレッドで異なるワークエリアを作成している、
つまり不完全ながらもマルチスレッド対応しているという見方もできる。
(実際どうかは知らん。メモリだけ確保して1つのワークを壊しまくってる可能性もある)
つか、なんでCreateThread()で試してるんだ?
試すまでもなく駄目なの分かり切ってるだろ。
_beginthread*()ならまだわからんでもないが・・・。
238 :
225 :2006/01/28(土) 18:02:37
> 複数のスレッドで同時に1つのワークエリアを参照していれば、
> 各スレッドがお互いに1つのワークエリアをぶっ壊しあう。
マルチスレッド対応のランタイムでは、そのような問題は起こらないことが
保証されているものだと思ってました。
_beginthread(ex) の説明を読む限り、メモリリーク問題以外については
何も記述されていません。
> つか、なんでCreateThread()で試してるんだ?
確認したかったのは、「A.EXE で作成したスレッド内で B.DLL 内の関数を
呼ぶことが出来るかどうか」だからです。
A.EXE は BCB5 で作成していて、B.DLL は VC6 で作成しています。
B.DLL 内の C ランタイムルーチンを使うのに、A.EXE の _beginthread(ex)
を使っても無意味なのは初めからわかりきっています。
また、
>>235 では書きませんでしたが、3.の場合、C ランタイムルーチン
はスタティックリンクされてるので、やはり A.EXE の _beginthread(ex)
と B.DLL の _beginthread(ex) は全く別物です。
> 試すまでもなく駄目なの分かり切ってるだろ。
メモリリークという点だけ見れば、駄目とは言い切れないという結果に
なったと思うのですが。元々 DLL_THREAD_ATTACH/DETACH で解決し得る
問題だと思ってるので、この結果がおかしいとは思えません。
>>238 > マルチスレッド対応のランタイムでは、そのような問題は起こらないことが
> 保証されているものだと思ってました。
思うのは勝手だけど、正しい使い方をしないと正しい挙動はしてくれないよ。
この場合、_beginthread*()を呼ばないと、「正しい挙動」はしてくれない。
なぜなら、Cランタイムをスレッドセーフにする肝心の処理を_beginthread*()がやるから。
ついでに言えば、問題はB.DLLだけの話ではなくて、A.EXEのランタイムに
何を使ってるか? というのも重要。にも関わらず、
>>235 でその点に
一切触れていない点からも、喪前さんの理解が足りないことが伺える。
240 :
225 :2006/01/28(土) 20:18:06
>>239 > なぜなら、Cランタイムをスレッドセーフにする肝心の処理を_beginthread*()がやるから。
_beginthread(ex) と _endthead がやるのは、スレッドごとに必要なメモリ
の割り当てと解放を行うことですよね?
_beginthread を使わなかったせいで、ランタイムルーチンを呼び出し時に
そのスレッドではまだメモリが割り当てられてなかったなら、その場で動的に
割り当てれば問題ないでしょう。実際、動的に割り当ててると思うんだけど。
問題なのは、スレッドの終了を知ることが出来なくなるせいで、割り当てた
メモリを解放する機会が得られなくなり、その結果としてメモリリークが発
生する、ということではないの?
_beginthread(ex) を使わないことによって、排他処理的な問題が起こるとは
どこにも書いてないですよね?起こらないとも書いてないけど。
排他処理的な問題が起こると明記されてるのは、シングルスレッド版の
ランタイムを使った場合の方だけです。
マルチスレッド版の方では、メモリリークのことしか書いてないと思う
んですけど。
> ついでに言えば、問題はB.DLLだけの話ではなくて、A.EXEのランタイムに
> 何を使ってるか? というのも重要。にも関わらず、
>>235 でその点に
> 一切触れていない点からも、喪前さんの理解が足りないことが伺える。
A.EXE は BCB5 で作成、B.DLL は VC6 で作成と書いてます。
理解が足りないのは認めますが。
長文ばかりで申し訳ない。
とりあえず消えろ
242 :
225 :2006/01/28(土) 21:09:14
>>241 真面目に質問してるつもりなんですが、そういうのが伝わらない
あたりが 2ch のイヤなところですね。
どこかにこの件に関してきちんと解説したウェブサイトなり書籍
があればご紹介頂きたかったですがね。
>>242 そういうのにいちいち気にしていたら駄目だよw
2chの使い方からまず学んだほうが有効に使えるかも。
当然俺のレスにもレスは要らないぞw(あってもいいけど
244 :
225 :2006/01/28(土) 21:40:13
>>243 やっぱりそうですか。(^^;
>>235 の結果から、(この検証が正しければ)メモリリークに関しては
処理系依存ということになったわけだし、ドキュメント化されてるわけ
でもないようだから、結局のところ結論なんて出ないんだろうな…。
「A.EXE で作成したスレッドから B.DLL の関数を呼び出すとメモリリークする」
のだとすると、Susie プラグインとか、自分ではメンテナンス出来ないプラグイン
方式の DLL を使うアプリをマルチスレッド化するのは非現実的ということになっ
てしまうのか…。ほとんどの DLL は C ランタイムを使用してるだろうから。
一度作成したスレッドはアプリが終了するまで使い回すようにするしかないの
だろうか…。なんか納得行かないな。
Susieプラグイン使う様なサイズのアプリなら、
スレッドプール使えば"about 70-80 bytes"のリークなんて気にする必要ないのでは?
>>242 MSDNだろ。
246 :
241 :2006/01/28(土) 22:09:50
マルチスレッドプログラミングをしたことのない房でも225のような真面目なやつを馬鹿にできるんだから 2chって憂さ晴らしに最適だよな。
>>244 真面目におかしなことばっかり言ってるから相手したくなくなるんだよ。
依存するのは処理系自体ではなくライブラリだし、
アンドキュメントな実装に依存したコードを書くのは無謀。
漏れが言えることは、
「EXE・DLLの両方で同じライブラリ使ってれば、相互に呼び合いしても問題ない」
「泥沼に足突っ込みたくなければ推奨されてるやり方を使え」
それだけ。普通にMSVCRT使えばいい。
それ以上のこと知りたいなら、AdvancedWindowsなりMSDNなりCRTのソースなり
自分で読んで勉強してくれ。スレでいちいち書けるほど単純な話でもない。
249 :
225 :2006/01/29(日) 04:20:43
>>248 > 「EXE・DLLの両方で同じライブラリ使ってれば、相互に呼び合いしても問題ない」
DLL は他人が作ってるので自分でいじれないし、EXE は GUI の
関係上 BCB しか使えないので。
> 「泥沼に足突っ込みたくなければ推奨されてるやり方を使え」
EXE で作成したスレッドから DLL の関数を呼ぶ場合の推奨されてる
やり方とは?EXE/DLL ともに MSVCRT を使うことですか?
> AdvancedWindowsなりMSDNなりCRTのソースなり自分で読んで勉強してくれ
MSDN と CRT のソースは自分なりに熟読してみたつもりです。
CRT のソースから、
>>235 の結果は予想通りでした。
でも、3.の結果は予想通りだけど納得行かない。
BCB5 の C ランタイムライブラリのバグと言うべきなんじゃないだろうか。
仕様で片付けていい問題ではないような…。
AdvancedWindows を読んでもう少し勉強してみます。
最後のはBorlandのドキュメント読まないと仕方ないでしょ。 使ったことないから、どういう事になっているのか知らないし、 それで仕様通りの利用かどうかもわからない。 いずれにせよ、サードパーティのDLL内で、 CreateThread()を多発してない限り、別に大きな障壁になることじゃないよね。 スレッドを多発する場合、スレッドプール使うのは鉄則だから。
まあスレッドプログラミングなんてやってる香具師はそんな香具師ばっかりだから
だから日本はだめなんだよな
256 :
デフォルトの名無しさん :2006/01/30(月) 17:17:51
マルチスレッドでプログラムを作っているのですが、VisualC++6.0(SP6)でデバッグすると しばらくするとフリーズしてしまいます。 フリーズというのは、VC++と実行しているEXEがまったく応答しなくなり、 さらにOSの反応がほとんどなくなる感じです。 ほとんどというのは、Alt+Tabぐらいは効くのですが、タスクマネージャーも起動せず 他のアプリも、しばらく動くのですがじきに応答がなくなります。 デバッグではなく、ただEXEを実行した場合は普通です。 OSはWindowsXPHome SP2で、まあ標準的な環境だと思います。 1つ怪しいのといえば、NortonAntiVirusですが、これに関しては ほぼインストールしたてのWin2000SP4のマシンでやっても同じような現象が 起こったので、他のアプリが邪魔している、というわけでもなさそうです。 それなりに長いソースなので、同様の問題が発生する簡単なソースをコピペします。
257 :
256 :2006/01/30(月) 17:18:38
#include <windows.h> #include <stdio.h> LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); char* szClassNme = "aaa"; DWORD WINAPI thread_proc(LPVOID param) { int i; while(1) { i++; Sleep(10); } }
258 :
256 :2006/01/30(月) 17:19:29
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPreInst, LPSTR lpszCmdLine, int nCmdShow) { MSG msg; WNDCLASS WClass; HWND hWnd; DWORD tid; if (!hPreInst) { WClass.style= CS_HREDRAW | CS_VREDRAW; WClass.lpfnWndProc= WndProc; WClass.cbClsExtra= 0; WClass.cbWndExtra= 0; WClass.hInstance= hInstance; WClass.hIcon= NULL; WClass.hCursor= LoadCursor(NULL, IDC_ARROW); WClass.hbrBackground= (HBRUSH)GetStockObject(WHITE_BRUSH); WClass.lpszMenuName= NULL; WClass.lpszClassName= szClassNme; if(!RegisterClass(&WClass)) return 0; } hWnd = CreateWindow(szClassNme, "aaa", WS_POPUP | WS_SYSMENU | WS_MINIMIZEBOX, 100, 100, 200, 200, NULL, NULL, hInstance, NULL); ShowWindow(hWnd, nCmdShow); UpdateWindow(hWnd); CreateThread(NULL, 0, thread_proc, NULL, 0, &tid);
259 :
256 :2006/01/30(月) 17:24:07
while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } return (msg.wParam); } LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) { switch (msg) { case WM_DESTROY: PostQuitMessage(0); break; default: return(DefWindowProc(hWnd, msg, wParam, lParam)); } return 0; }
260 :
256 :2006/01/30(月) 17:30:36
thread_procの、while(1)のところにブレークポイントを設定し F5を連打し何回かループさせると、いずれ固まります。 ひょっとしてプログラムに何か原因があるのでしょうか? デバッグがままならないとなると開発が非常に困難です。
261 :
256 :2006/01/30(月) 20:19:40
WinXPで、ウィンドウズキー+Lで、ユーザーを切り替ることはできたので 別のユーザーからMSDEV.exeを強制終了すると、一応復帰できることが分かりました。 しかし、依然として非常に困っています。 もし以前こんな現象に見舞われたけど、こうして直したよ、とか ここをこうしたらいいんじゃないの?っていうのがありましたらぜひ教えていただきたいです。
osの再インストールしても直らなかったという、ほろ苦い思い出があるよ。
263 :
256 :2006/01/30(月) 21:32:25
>262 その後は結局どうなりました? ひょっとしてマルチスレッドのデバッグは、VC++6.0でできないっていうのが 「仕様」なんでしょうか?
Windowsを2000にするか、VisualStudioをバージョンアップしませう
265 :
256 :2006/01/30(月) 22:01:27
>264 Windows2000でもなりました。 VisualStudioをバージョンアップですか.... 高かったんですよね。
>>256 私も Windows2000 から XP にアップグレードしてから似たような
現象が発生するようになりました。
VC++6.0 と BCB5 でそうなっていて、どちらもマルチスレッド
アプリケーションでなくても発生します。
なんか Window メッセージの送受信の応答がシステム全体でとてつもなく
遅くなる感じですね。バックグラウンドで音楽とか流していても、音楽は
普通に流れますが、ウィンドウの切り替えとかがものすごく遅くなります。
完全なフリーズじゃないだけに、諦めて電源を落とそうにも、落とすタイ
ミングに困ってしまうというか。
ttp://www.wg7.com/w2ktips/#CTFMON これと似たような症状なんですが、私は試していません。言語バーが
使えなくなるのも困るので。
結構頻繁に起こるので辛いのですが、起こらないときは起こらないので、
そういうものだと思って諦めています。
267 :
225 :2006/01/30(月) 22:43:46
_beginthread(ex) の説明のところに、CreateThread だとメモリリークして
しまう C ランタイム関数の一覧でも書いてあれば良いんですけどね。
ttp://support.microsoft.com/?scid=kb%3Ben-us%3B104641&x=11&y=5 には malloc とか fopen でもメモリリークするようなことが書かれてるけど、
実際に試してみると、VC6/BCB5 どちらの場合もメモリリークしてるようには
思えないです。
ここに書かれてないものでは、rand() を使うとメモリリークしますね。
今回の呼び出しの結果が前回の呼び出しに依存するようなタイプの関数は
全滅なんでしょうね。
268 :
256 :2006/01/30(月) 22:55:37
>266 確かに今まで他のプログラムを組んでいるときにそういうことはありました。 しかし、今回はそれとはちょっと違うように思えるのです。 一度固まると、少なくとも20分ぐらいは待ってみたのですが復帰しませんでした。 しかも、ほぼ毎回起こります。 上のソースに何か問題点があるのでしょうか? ウィンドウメッセージに応じて処理をするスレッド(最初に起動されたときのもの) 別に他の計算をするスレッドを別に作っています。 競合が起こっているのかと思い、上のような簡単な簡単なソースを書いてみたのですが あれでも必ずといっていいほど起こります。 ちなみにWindowsMeでも起こりました。家のPC全滅です..
269 :
266 :2006/01/31(火) 00:34:55
最初は自分が書いたプログラムに原因があると思ってたのですが、 Web 上にある他人が書いたもののいくつかを自分の環境でコンパイル・実行 してもそうなるので、環境によるものだと思って諦めることにしました。 Windows2000 では問題なかったので、256 さんと私とでは状況が 少し異なりますね。マルチスレッドアプリケーションでなくても 発生しますし。お役に立てなくてすみません。
オレもよくなる。ステップ実行しているとなんでもないところで固まってCtrl+Alt+Delをやって再起動とかやるが まったく動かず、次にAlt+Tabで悪あがき。選択した窓から順に固まる。 最後電源長押し、するとmsdev.exeを終了しています、かなんかがでて、msdev.exeが終了するとほかもサクサク終わる。 もちろんまったく終わらないでそのまま固まることもある。 DLLで提供される関数をステップオーバーしたときに出るとか、なんか最初はそんなことを思っていたけど そうでもないらしい。
Windowsのスケジューラ糞馬鹿だから タスクマネージャでMSDEV.EXEのプライオリティ上げろ。
272 :
256 :2006/01/31(火) 21:11:22
VisualStudio .NET 2003を入れてデバッグしてみたところ、簡単なものは ほとんど固まらなくなりましたが(とはいえ、ごくたまに固まります) 開発しているプログラムは依然として固まるようです。 いまいちすっきりしないのですが、あまりこの問題にかまっている時間的 余裕も無いのでデバッグ時のみシングルスレッドで動くようにして 場当たり的な解決をすることにしました。 幸運にもあまり修正せずにすむに済みました。 依然として自分のプログラムに問題があるのかという不安はのこりますが... 266さんをはじめ、皆様、様々な情報提供ありがとうございます。 よくあることのようなので、少し安心しました。(していいのか!?)
257のコードで何にも問題は出なかったぞ。 F5押しっぱなしでも固まるどころか快調そのもの。 Dual Pentium III 1GHz, NT4.0 VC++ 6.0+Sp5
>>256 デバッグモードでなぜかおかしくなるというWin個体は確かにある。
どうしようもない。マシン変えろ
276 :
sage :2006/02/04(土) 00:23:14
VB6.0でActiveX DLLを使用し、マルチスレッドを実現できるという噂を聞いたのですが 本当ですか? でもイメージが掴めない・・・ VBでActiveXコンポーネント「A」を呼び出し ↓ A作成→A何らかの処理 ↓ VBの処理←A処理終了 ↓ VB次の処理 って感じでマルチスレッドとは違う気がするんですが・・ もし本当であれば、どなたか参考になるサイトをご教授頂けませんでしょうか
277 :
デフォルトの名無しさん :2006/02/04(土) 01:43:21
>>276 DLLの中はC++で書けばなんでもやり放題なんじゃね?
DLLの中でクリートスレッド
CreateとDeleteの合成語だろ スレッドを作ったら自分で閉じろってことだ
>>276 ActiveX のコンポーネントとして作成した DLL/EXE が
スレッドセーフだ、ってだけじゃね?
何をしたいのかしらんが COMのスレッドは楽しいぞ
CreateThreadをクリートスレッドって読んだんだろ。 馬鹿みたいだが。
284 :
デフォルトの名無しさん :2006/02/11(土) 07:40:21
もう二日も考え込んでるんですが解決しないんで質問です。(うう、マジで目と頭が痛い…。) 基本的に生産者消費者問題なんですが Aが物を作るとBに渡し、Bが物を作るとCに渡し、Cが物を作るとDに渡す、というように 複数の生産者/消費者のベルトコンベヤーでの流れ作業を想定しています。 で以下のように組んでみたんですが、 今度はB自身が消費したことをB自身に知らせなくてはならなくてこんがらがってきました。 public class Main { public static void main(String args[]) { ConveyerBelt stationAB = new ConveyerBelt(); ConveyerBelt stationBC = new ConveyerBelt(); ConveyerBelt stationCD = new ConveyerBelt(); Worker producerA = new Worker(stationAB); Widget consumerB = new Widget(stationAB); Worker producerB = new Worker(stationBC); Widget consumerC = new Widget(stationBC); Worker producerC = new Worker(stationCD); Widget consumerD = new Widget(stationCD); producerA.start(); consumerB.start(); producerB.start(); consumerC.start(); producerC.start(); consumerD.start(); } } ConveyerBelt()バッファーが三つというのは正しいと思うんですけど スレッドはABCDの四つだけ作ればいいんでしょうか?どなたかご教授下さい。
285 :
284 :2006/02/11(土) 07:43:18
ちなみにセマフォは「なし」の方向でお願いします。
日本語で質問してください
>>284 Chain Of Responsibility パターンはもう検討済みなの?
>>284 4つじゃないとダメなわけもないし、好きに作ればいい
各々理由を書いてね。 > 今度はB自身が消費したことをB自身に知らせなくては > ならなくて > ちなみにセマフォは「なし」の方向でお願いします。
>>289 正確厨、規格厨、口先厨の予感。現状提示されている情報から
回答が思いつかなければ、その問題に対する類似性や経験則
など思い当たるところが無いっつーことだろ。
全部の情報が分からないとコミュニケーションできないような
応用力無しやつは黙ってろ
293 :
291 :2006/02/11(土) 22:33:21
せっかく流れ切ったのに…
>>290 やんわりと、「設計がおかしいんじゃないか?」と言われてるんだよ。
まあ、もうまともな回答は期待できないだろうからどうでもいい話だが。
295 :
284 :2006/02/12(日) 01:45:30
ご迷惑をお掛けしております。m(__)m
>>287 そんな概念があったんですね。というくらいなので検討済みではないです。
検索してみていくつかサイトを見つけたのでもう少し読んでみます。
分からなければまた質問します。それと
if (Thread.currentThread() == "Thread[Thread-0,5,main]")
System.out.println("I am the Worker A.");
のようなチェックを入れたいんですが、そんな比較はできないみたいです。
左辺値はどんな感じにすればいいんでしょうか?
これができれば、一つ一つ鎖をつなげていける気がするんですが。
>>288 逆を言うと「4つでもできる」ということですか?
>>289 現状を話しますと
Aから渡された物をB自身が処理(消費)してもないのに
(いや、時にはAから物を渡されてもないのに)
Bは勝手に生産を始めてしまいます。
ですから現在はA-B間、B-C間、C-D間のみで同期がされてます。
それと、やっぱりセマフォアは「あり」でもいいです。
296 :
デフォルトの名無しさん :2006/02/12(日) 05:05:21
ここでは綺麗でも汚くても叩かれますYOW
誤爆した スマン...
>>294 その「やんわりと」の部分が他人をイラつかせるんだよ。現実でも
相当にいやみな人間だろう
>>292 そこまで行間が読めないようだと生きるのに苦労してないか?
>>299 292は皮肉で言っただけだから、普段は別段苦労はしてないな。
この業界、日本語の喋れない奴ばかりだからエスパー能力は必須だよね 低級エスパーだから日々苦労してるよ
エスパーってほどか? そうじゃなくてだな、俺の言いたいことはだ、 類似の問題を経験していたら回答が思い浮かぶだろ。素直に それ書いてやりゃいいんだ。お前らだって今まで誰かに教えて もらったり助けてもらったことあるだろうに。 それを忘れてくだらねー皮肉や、重箱の隅をつつくようなまぜっかえしを 親切を装ってやるようないやらしいことすんなよ。ナサケナス
別に2chで教えようと混ぜっ返そうとどっちでも構わんと思うのだけど。 まぁ、ヒントだけ貰った方がいい場合と答丸ごと貰った方がいい場合があるのでどっちがいいとも言えないしね。 漏れはここのスレでは教えることも教わることも少ないけど、この板全体では教わることより教えることのほうが多くなるようにしている積もりだがね。 混ぜっ返したり揶揄したり誘導したりも多いけどw
304 :
284 :2006/02/12(日) 12:23:35
で、あのー・・・
生産者消費者問題くらい、標準的なテキスト読んで自分でやれ
306 :
284 :2006/02/12(日) 12:37:41
テキストには生産者消費者が一対一の例しか載ってないんですよ。 こんなに真剣に質問してるのになんでこんな目に遭うんだ… 世の中絶対におかしい。
307 :
284 :2006/02/12(日) 12:38:49
丸投げでもなく真剣に書いてるのに…もう馬鹿馬鹿しくて泣けてきた…もういいです。
なんで、consumerBとproducerBが別オブジェクトなわけ? ふつうは入口と出口のある1つのオブジェクトとして考えるでそ?
お前らかわいそうだから教えてやれ。おれは良く分からないのでパス。ごめん
レベル1エスパーだけど、
>>284 >> ConveyerBelt()バッファーが三つというのは正しいと思うんですけど
>> スレッドはABCDの四つだけ作ればいいんでしょうか?どなたかご教授下さい。
唯一の正解があると思ってるのか?好きにつくれよ
>>306 質問する相手を間違えているだけだろう?
世の中がおかしいのではないと思う。
普通はレスの付き方を見て、質問の仕方が悪いと思うんだけどね
>>284 漏れも>308の言うとおりだと思う。
つか、めっちゃ単純な問題だと思ってたから
まさかconsumerBとproducerBが別だと思ってなかったw
あらためてソース見直してみてビックリした。
> ですから現在はA-B間、B-C間、C-D間のみで同期がされてます。
それでいいんじゃないの?他に同期取らなきゃいけないの?セマフォもいらんと思うけど。
>>313 > 他に同期取らなきゃいけないの?
知りもしないのに、
> セマフォもいらんと思うけど。
云うな(w
うん、ごめん。よくわかってなかったわ。 最初ConveyerBeltの作り疑ってたもんな。 危うく恥かくとこだった。
316 :
289 :2006/02/12(日) 13:51:11
俺も、
>>308 に同意。
だから、
> 今度はB自身が消費したことをB自身に知らせなくては
> ならなくて
は、何か勘違いしてんじゃないかと思って、
>>289 を書
いてる。はじめのうちは、(俺も含めて) 結構とんでもな
い勘違いをすることがあるから、別にそれがおかしいとは
思わないけど、何を考えてるかわからんと情報を提供して
あげることもできないから。
あと、
>>306-307 が本人かどうか知らんけど、「真剣に
質問」したのにまともな答えが返ってこないと言うが、
匿名掲示板に質問すること自体が既に「真剣に質問」して
いるとは言えない。回答する方は、あくまでも知ったかし
たいか暇つぶしか昔の恩を返したいかなんだから、「真剣
に向き合え」とか言われたら、「なんちゃ、それ。」で無
視されるのがオチ。
この板の人は基本的に親切だから、嘘は余り書いてない。
>>290 みたいな雑音を飛ばしてよく読めば、きちんと
ヒントは書かれているから、自分でググルなりすればいい。
そのものズバリの答えが欲しいなら、本を買うなり学校に
通え。
実質何も答えていないのを繰り返してるだけじゃね?
答える側が堂々巡りするケースのほとんどは、 質問がいい加減なことに起因する。
320 :
289 :2006/02/12(日) 15:47:02
>>317 まあ、確かにそのものズバリの回答は無いけど、
>>287 ,
>>308 あたりは、充分ヒントになりうると思うが。
個人的見解として、このヒントを基に自分で勉強するぐら
いでないとマルチスレッドのプログラミングはできないと
思う。
変なところで改行するなよ 醜い
久し振りに来てみたが、相変わらず、このスレは知ったか馬鹿が多いな。
とりあえず
>>288 、
>>310 、
>>311 あたりの馬鹿どもはこのスレいても邪魔だから消えろ。
もう
>>284 はいないと思うが俺なら
public class Main
{
public static void main(String args[]) {
ConveyerBelt NULL = new ConveyerBelt();
ConveyerBelt stationAB = new ConveyerBelt();
ConveyerBelt stationBC = new ConveyerBelt();
ConveyerBelt stationCD = new ConveyerBelt();
Worker workerA = new Worker(NULL, stationAB);
Worker workerB = new Worker(stationAB, stationBC);
Worker workerC = new Worker(stationBC, stationCD);
Worker workerD = new Worker(stationCD, NULL);
workerA.start();
workerB.start();
workerC.start();
workerD.start();
}
}
とやる。ConveyerBeltクラスん中ではinとoutの二つのbufferを作ってやれ。
>>322 > ConveyerBelt NULL = new ConveyerBelt();
> ConveyerBeltクラスん中ではinとoutの二つのbufferを作ってやれ。
馬鹿ジャネーの。
324 :
デフォルトの名無しさん :2006/02/15(水) 00:03:38
俺も > ConveyerBeltクラスん中ではinとoutの二つのbufferを作ってやれ。 は意味わかんねえ。ConveyerBeltなのに何か処理でもするの?
>>325 多分、in と out の buffer を取り持つ ConveyerBeltSub
を作るんだよ。
もちろん、その中には buffer が二ついるから、更に
ConveyerBeltSubSub を作って...。(w
#
>>322 =
>>324 は、基礎から勉強しなおした方がいいぞ。
buffer1個でいいでしょ
どうでもいいけどなんで4つとも別スレッドで独立して動かす必要がるわけ? 全体としてどんなことをしたいのか今一想像がつかん。
あらあら、もう一人馬鹿↑が来た お前、流れ作業って言葉聞いたことあるか?
>Aが物を作るとBに渡し、Bが物を作るとCに渡し、Cが物を作るとDに渡す、というように
>複数の生産者/消費者のベルトコンベヤーでの流れ作業を想定しています。
>>327 お前の読解力は小学生以下か?
buffer一つで出来るもんならやってみろ、馬鹿。
出来ないんならもう来るなよ、ここではお前は邪魔なだけだから。
パイプ1個あたりバッファ1個の意味で言った 言葉足らずというか全然意味が通らないねスマソ
Java よく知らんのだが、これは要するに 4つのスレッドを3つのキューで繋ぎたい、って「だけ」の話?
YES
>>329 いやそうじゃなくてどんな処理で4スレッドの流れ作業なんて必要になるのか
想像がつかんのだ。
マルチ商法ですた
そんなもの想像つかなくていい。 質問に答えりゃそれでいいんだ
関連する複数のタスクを回す場合は、個別に分けずに スレッドプールでまとめてやるのがいいんじゃないの? やろうと思えばExecuterServiceでも似たようなのできるけど。 □ タスク側 1. 自身のタスク終わったら次のCallableをsubmit()する。 2. 途中のタスクの戻り値としては次のFutureを返す。 3. 最後のタスクは流れ作業全体の値を返す □ 呼び出し側 1. ExecuterServiceに最初のCallableをsubmit()する。 2. Futureのget()がFutureを返した場合は置き換えてループする。 3. Future以外が返って来たら全タスク完了。 ただ、Callable中で次のタスクをsubmit()すると、バウンド形式なQueueで 最大スレッド数に制限が付いてるとデッドロックの可能性があると思われ。 これはExecuterServiceを流れ作業の数だけ作れば回避できそうかな?
>>333 d楠。
たったそれだけの事で、こんだけ盛り上がれるなんて
なんの病気なんだ…
>>334 それを実現する手段を知るためじゃね?演習問題みたいな。
>>332 たぶんそう。それなのにbuffer二つとか言い出す奴もいて…
そもそも質問があれだし。
みんなコロンブスの卵って知ってる?
「コロンブスの卵」は、「誰にできることでも、最初にするのが難しい」という意味で使われる。
1492年にアメリカ大陸(西インド諸島のサンサルバドル島といわれている)を発見したことで有名なコロンブス。
その功績を祝う晩餐会で、ある男が言った「西へ西へと航海して陸地に出会っただけではないか」と言った皮肉に
対して、コロンブスは卵を取り上げ、「この卵を卓の上に立ててごらんなさい」と言った
だれも立てられないのを確認するとコロンブスは、卵のおしり(気室のある鈍端部と思われる)を食卓でコツンとた
たいて立てて言った。「人がした後では何事も簡単です」
>>332 で、その「だけ」の話を理解できなかったのはどこの馬鹿だったっけ?( ´,_ゝ`)プッ
なにこの馬鹿…
ああ!この↑馬鹿か、その「だけ」の話を理解できなかったのは!
文章から頭の悪さが滲み出ている。
↑「だけ」の話を理解できなかったのが相当悔しかったんだね。( ´,_ゝ`)プッ
なんか雰囲気が悪くなってきたな。 元に戻そうぜ。 これって Aの生産量≦Bの生産量≦Cの生産量 だよね?でないとCとかDとかが結構待たされるんじゃないのかなーと。
↑何もわかってない奴の典型だな!
と、必死。
ここにいるのは馬鹿ばっかだな
>>345 ふいんき(←なぜか変換できない)戻そうと必死なのは分かるが
流れ作業なので
Aの生産量=Bの生産量=Cの生産量
荒らしの相手はやめようや。
>>334 今思い出したが、以前C++ on Windowsで似たような構成にしたことあったわ。
その時は通信スレッド×20→データベーススレッド×2→印刷スレッド×1だったが
キューとミューテックス(各1)で小さいクラス作ったような覚えが。
>>350 なんで?
極端な話、Aが2つの整数を流してBがそのxorを流したら半分じゃん。
まぁ別にそんなのはどうでも良くて、
単に4つスレッドを作らなくちゃいけない状況を想像して見たかっただけ。
邪魔してすまん。
10メガくらいのメモリをコピー(memcpyとか)するときに、 領域を分割してマルチスレッドにしたら速度上がる? マルチコアとかマルチスレッディングなら上がるかな?
memcpy()だったら変わらない希ガス fread()とかで、あるスレッドでHDDからデータ読み込み中に、 前回読み込んだデータ解析を行うとかだったらスループットはあがると思う。
>>353 CPUが速ければ、
キャッシュを含めたバスシステムがボトルネックになるまでは上がる。
システム依存だから自分のターゲットにしているヤツで試してみて。
356 :
353 :2006/02/22(水) 08:10:39
ありがとう。 でも本当はそんなメモリコピーしない設計にするのがいいんだよなorz
じゃあ、なんでそんな設計にならざるを得なかったのか、説明してみればいいじゃない。 メモリ参照だけで済むアルゴリズムを誰かが教えてくれるんじゃない?
writeで例外起こすようにしてcopy-on-writeだ
設計したのは赤の他人。 ワタシはメンテ担当(涙)
>>359 その赤の他人よりも上手に設計できたとおもう?
何このウスラ馬鹿な突っ込み
>>359 設計思想もわからん個所を、色々チューニングしようとしてるの?
悪いことは言わないから「やめとき」。
仕事じゃしょうがないよな。
364 :
デフォルトの名無しさん :2006/03/03(金) 07:10:31
UNIXでC++なんですが、
ttp://d.hatena.ne.jp/yupo5656/20041011/p3 ここに載っている、
スレッドローカルストレージを使ったシングルトンの実装って安全でしょうか?
だいたいこんな感じになってます。
public:
static T& getInstance(void) {
static __thread T* tsd_instance = 0;
if (!tsd_instance) {
tsd_instance = getInstance_();
}
return *tsd_instance;
}
private:
static T* getInstance_(void) {
boost::mutex::scoped_lock lk(m);
if (!instance) {
instance = new T;
}
return instance;
}
ISO C++の範囲内でポータブルな実装はないんだ。
>>291 を読め。
>>364 安全ですよ。
getInstance_(void) が既に安全なわけで、
tsd_instance の方は覚えとくだけで、
かつ単一スレッドからしか参照されないので。
メモリモデルの問題については、
たぶんscoped_lock の解放でメモリバリアも処理されるんでしょう。
(pthread のドキュメント呼んでないのであてずっぽう)
>365 364はDCL関係ないじゃん
>>366 POSIXではmutexの開放はメモリバリア。
369 :
デフォルトの名無しさん :2006/03/05(日) 00:20:02
>>340 普通の卵は比較的簡単に立つよな。表面に凹凸があるから。産みたてほど立ち易い。
・・・コロンブスは卵をツルツルに磨き上げていたに違いない。
>>370 まあまあ。
コロンブスもギャグで言っただけなんだから許してやってくれ。
後世の作り話ですから。
まあ
>>340 は底抜けの馬鹿だけど。
ゆで卵にして高速で回せば立つよ。
まあ
>>372 は底抜けの馬鹿だけど。
盛り上がっているところ、横から突っ込んでスマンけど。 生卵を立てるには塩をごく少量盛って、その上に立てて、横から 息をゆっくり吹きかけて塩を飛ばすといいという話を聞いた。 とかいう本当にどうでもいい話をマルチスレッドスレでする 自分は底抜けの馬鹿ですw
つまり塩スレッドに卵スレッドをロックさせれば桶?
卵スレッド発見
377 :
デフォルトの名無しさん :2006/03/08(水) 20:55:31
君ほどでも
ゆで卵の殻を剥かずに塩をかけるなんて、底ぬけの馬鹿ですね
観光地のゆで卵は全部そうなってるよ
>>379 卵殻はNa+イオンもCl-イオンも透過するのでちゃんと卵に塩味がつきます。
溶けさえすれば。
※注意: このスレはこの卵ネタで1000まで引っ張る覚悟です
たまごが立つという状態を定義してください。
ブスの卵
>>383 案1:
水平方向の任意の角度から卵を投影したときに、水平方向のスパンよりも鉛直方向のスパンの方が長い状態。
ただし卵が他の物体と接することができるのは下部のごくせまい部分のみとする(←うまい定義できないなこれ)
ポテンシャルの極大点。
あ、あんたなんかにたたれてもうれしくないんだからねっ!
>>383 おまいはコンピュータか? んなもん定義しないでも分かるだろ
クララが立った、と言う状態を定義してください。
精神的な自立
それで泣ける、という状態を定義してください。
クララが勃った、と言う状態を定義してください。
クララが勃った クララは女である ∴よって勃ったのは乳首である
class clitoris extends electiliable {
>>394 なんだ、選挙にでも出るんか?
…それを言うならerectibleだろ。
396 :
デフォルトの名無しさん :2006/03/12(日) 16:25:47
Win32 Administrator権限で実行されてるプロセスからスレッドを起こすとき、 スレッドそれぞれに異なるユーザー権限を設定することは可能? プロセスごとならできるんだが。もし可能ならAPI名などヒントを頼む。
インパーソネーションとかいうんだっけ? ImpersonateLoggedOnUserとか。 まー、RevertToSelfとか呼ばれると、元に戻るけどね。
>>397 ありがd。
まだ試せてないが、MSDNの説明から目的に適うAPIのよう。
なぁなぁ、 class Job extends Thread { public void run() {} } class MyJob extends Job { public void run() {} } ってあったらMyJobのrun()がJobのrun()をオーバーライドするんで Jobのrun()に書いてある定義とか全部無視されちゃうよね? ちゅーか、Jobのrun()の一行目に System.out.println("Hello? Hello? Can you read me?");//never displayed と書いても表示されないから間違いない。 でも、どうやったら両方のrun()とも動かすこと出来るんだろ?
400 :
デフォルトの名無しさん :2006/03/15(水) 14:42:42
一応ageとく。
>>399 1つのスレッドで順番に動かしたいのか?
MyJob.run() と Job.run() を別のスレッドで動かしたいのか?
MyJob と Job のインスタンスをそれぞれ作ったらいけないのか?
402 :
デフォルトの名無しさん :2006/03/15(水) 15:48:21
>>401 ありがと。
二番目の「別のスレッドで動かしたい」かな。
run()直接アクセスするとあかんのよね、.startで始めないと?
どうしようかな?
>>402 その手法が可能かどうかの前に、やろうとしていることに対して
もっと単純な方法や、別の解法が無いか検討したらいいんじゃ
ないかな。
ちょっと言語(Java?)の使い方から外れているみたいので、
本当にやりたいことが妥当かどうか見極めた方がいいと思う。
405 :
デフォルトの名無しさん :2006/03/16(木) 09:59:17
>>403 確かにそうだったかもしれん。ありがと。
>>404 いや、直接run()にアクセスするのは禁(ry
Linux 2.4.31-0vl1.8smp + glibc-2.3.3-3vl1.3 pthread (linuxthread) プログラムでたまーに(でも確実に) seg fault してしまいます。 該当箇所は pthread_mutex_unlock(&mutex_sleep); という処理で、mutex_sleep はグローバル。core dump に聞いてみたらこんな返事が。 Program terminated with signal 11, Segmentation fault. #0 0x080551c7 in __pthread_alt_unlock (lock=0x80cb548) at spinlock.c:600 } else if ((prio = p_node->thr->p_priority) >= maxprio) { (gdb) bt #0 0x080551c7 in __pthread_alt_unlock (lock=0x80cb548) at spinlock.c:600 #1 0x08051fc9 in __pthread_mutex_unlock (mutex=0x80cb538) at mutex.c:199 #2 0x0804e3cc in send_proc (arg=0xc) at send_proc.c:112 #3 0x08051709 in pthread_start_thread (arg=0xbdbffbe0) at manager.c:309 何か情報ありますか?
mutexがすでに死んでるとか?
Windows Threadについて質問です。擬似コードですが、 Thread[] threads = getAllThread(); foreach (Thread t; threads) { t.suspend(); } このような全てのスレッドを止めるためのループがあるとします。 このループ中では、既に止められているスレッドと、 これから止められる予定のスレッドがあると思うのですが、 これから止められる予定スレッドが、既に止めたスレッドを再開(resume)するため、 このループでは全てのスレッドを止められない、ということは起こりえるのでしょうか?
>>408 起こりうるでしょうね。
避けたいのならばまず自分の優先順位をトテモ高くして、
その後ループに入れば良いと思います。
先方のスレッドも優先順位を上げている恐れがあるのならば
完全ではありませんが。
知らね。 だって、普通そんな造りにしないもん。 普通は、終了しろ、っていう合図を各スレッドに送って 自主的に終了なり中断なりするのを待つだけだから。
起こりえる。 おまけにこれから止めようとするスレッドが新たにスレッドを作るかもしれない。 全スレッドで、「スレッドマネージ用ミューテックス」などを使用すればいいんでない?
他のスレッドを suspend するってのはまず間違いなく設計ミス。 C のランタイムとか Windows に用意されているいろんな dll の 内部まで良く知っていて、何か大事なものの所有権を持ったまま suspend されちゃったりすることはないと確信を持っているなら 別だけど。
413 :
408 :2006/03/16(木) 22:46:12
どうも。 実は、これのpause版とresume版がD言語の標準ライブラリの中にあって、 GCを呼ぶ前にそれでスレッド止めて、後に再開ようとしているみたいなのですけど、 それのへんでアプリケーション側で実装しているスレッドの同期が変になるみたいです。 安心できませんが、安心しました。
414 :
408 :2006/03/16(木) 22:52:58
スレッドを止める仕様はどうしようもないのですが、 とりあえずは、全てを止めるループ中(pauseAll)に pause()、resume()とstart()が実行されないように排他とと 全てを再開(resumeAll)中に、resume()が実行されないように 排他したら大丈夫ということでしょうか?
>>414 GC 側が単純なメモリ操作などだけで、
他の処理で使っている(かもしれない)セマフォやミューテックスなどの
所有権なしで実行できるとするなら、問題ないはず。
例えば(MSのドキュメントを信用するなら)Windows API の OutputDebugString は、
内部で他のスレッドを全て Suspend した上でデバッグメッセージの送信を行い、
そののち Resume する、と同様の処理を行っているようです。
AP側のスレッドが変になるのはAP(or Dの何か他のライブラリ)のバグではないでしょうか。
416 :
408 :2006/03/16(木) 23:28:41
>>415 resumeThreadの戻りを見ながら、他スレッドのsuspend待ちをしている箇所があるので、
それが、排他されていないresumeAll中に走ると、
GCが止めてこれから再開する予定のスレッドを、
"アプリケーションが思っている理由"でsuspendしたのだと
勘違いして変になるのだと思っています。
>>407 ありがとうございます。
pthread_mutex_destroy は呼んでいないので生きていると思っていたのですが、どうやら
syslog(3) が関係しているようです。別の core dump に聞いてみたら syslog 関数で死んで
いるケースが見つかり、付近の syslog(3) をはずしたら seg fault することはなくなりました。
syslog(3) と pthread (linuxthread) は混ぜるな危険とかいう話があるんでしょうか。
とりあえず syslog を自前で用意することにしてみます。
その環境ではsyslog(3)はMT-Safeじゃないのに、排他してないだけとか
419 :
http://www.vector.co.jp/soft/win95/util/se072729.html :2006/03/18(土) 19:49:50
TextSS のWindowsXP(Professional)64bit化おながいします もしくは64bitにネイティブ対応したテキスト置換ソフトありますか?
420 :
デフォルトの名無しさん :2006/03/28(火) 00:13:15
こんな問題助けてください。 I/Oバウンドな処理をする処理プログラムが2個 CPUバウンドな処理をするプログラムが1個 それぞれCPUは85〜95%占有するほど負荷が大きいです。 またそれぞれI/O処理は多重スレッドはなく2つの独立した スレッドプログラムです。 Xeon 64bit x2 (64bitSMPカーネル+ HTTでCPU4個) Xeon 32bit x2 (32bitSMPカーネル+ HTTでCPU4個) Opteron 252 x 4(64bitSMPカーネル) Opteron 252 x 4(32bitSMPカーネル) いずれの場合も、CPUを占有したいと考えるならばcpu_affinityを ハードウェア的に割り当てるべきなのでしょうか。 それともカーネルのSMP処理に任せるべきなのでしょうか。
page outないくらいメモリが十分にあると考えると、 (OSによってはI/Oキャッシュがメモリを食い潰してしまいますが) I/Oバウンドな処理をするプログラムにCPU割り当てる意味ないでしょ。 けど、 > それぞれCPUは85〜95%占有するほど負荷が大きいです。 で「I/Oバウンド」なの? それからマルチスレッドじゃないw
>>420 CPU占有を占有したいなら、邪魔しに来る恐れのあるほかのプロセスは
どれか他のCPUに割り当てるべき。
CPUを占有することの利点は、
・他のCPUでの処理の邪魔をしない
・各CPUが独立した2次キャッシュを持っているとき、キャッシュの汚染に
よるパフォーマンス低下を避けられる(かもしれない)
の2つくらい。
カーネルに任せるべきかどうかはなんともいえない。
プログラムの性格にもよるし、カーネルのスケジューラーの実装にもよる。
ぶっちゃけ聞きたいんだが、 「cpu_affinityをハードウェア的に割り当てる」 って、現在存在するOSの中でどれよ?
C++で質問ぬ beginthreadexで作ったスレッド exitthreadexしないで スレッド関数return で終了して CloseHandleしても問題ないですか? サンプルで exitthreadをreturn の前に呼んでるのと 呼んでないの があったので
>>424 寧ろ、exitthreadするとC++のデストラクタが走らないので問題になりがち。
極力returnするべき。
426 :
デフォルトの名無しさん :2006/04/06(木) 01:56:06
世はSPEでプログラミングしたいのじゃ
世界で始めてデッドロックを実際に経験した人って誰だろう。 あまりにもの恐ろしさに震え上がったことだろう。
俺
430 :
デフォルトの名無しさん :2006/05/06(土) 22:23:42
哲学者よフォークを取れ!!
先生、フォークが足りません!!
フォークを取ってどうすんだよw
通じてないのかさらに深い洞察なのか…
そうかパスタを取れか!!
435 :
デフォルトの名無しさん :2006/05/06(土) 23:50:03
>>434 てめー、すました顔してないで早くフォークよこせよ
436 :
デフォルトの名無しさん :2006/05/06(土) 23:54:39
まず全てのフォークをいったんテーブルに戻して、 そして... 哲学者よフォークを取れ!!
すまん、記憶違いだったら悪いんだが。 哲学者よときたら「箸をとれ」じゃなかったか?
ヒント:ダイクストラ
哲学者よ 死ぬくらいなら手づかみで食え
哲学者はきわめて明確な論理で行動するため、 臨機応変などという言葉は通用しません。
哲学者は、野蛮では無く極めて理知的に出来ております。
Dining Philosophers Problem は設定がシュール過ぎて 授業中に笑い出しそうになった
シュレディンガーが猫を題材にしたのと通じるものがあるな
お前なーやめろよ 話の流れから シュレディンガーが猫を食材にしたのと通じるものがあるな と読んじゃったじゃないか まぁ、たいして違いはないが
哲学者よ、明日はパスタにしよう。うん、パスタ。
哲学者は手掴みで食べないものなのですか?
哲学者はそんなはしたないまねはしません。 しかし決して人に譲ることもしません。
450 :
デフォルトの名無しさん :2006/05/08(月) 00:23:38
哲学者よデスマーチから逃げれ!!
451 :
デフォルトの名無しさん :2006/05/08(月) 09:39:33
age
Cでスレッド固有のグローバル変数みたいなものって使えないかな ほぼ全ての関数でスレッドごとに値の違う変数使ってるんで 毎回引数に加えるのが面倒になってきた
処理系固有でTLSなどがあるとは思うが。
gccだと、 __thread int i; とか。
調べました pthreadだとpthread_key_create()とかですね __threadの方が扱いやすいけどポータビリティとしてはどうなんだろう gcc依存でも別に困りはしないんですけどw 何はともあれありがとうございました〜
結城浩のデザインパターン スレッド編って買い?
. -‐- . __ 〃 ヽ : :ヽ\ ノノノ)ヘ)、!〉 : '. l(0_)!。-‐ ‐〈リ .はわわ〜マルチが459ゲットですぅ… ;Vレリ、" (フ/ ; : l´ヾF'Fl : ∧__∧____ ;. 〉、_,ノ,ノ : /|・∀・ ┥ ./\ . /ゝ/´, ヽヽ . . /| ̄∪∪ ̄ ̄|\/ : く/l |_ノト‐'⌒),) . | 拾って |/
460 :
デフォルトの名無しさん :2006/05/20(土) 17:07:49
461 :
デフォルトの名無しさん :2006/05/22(月) 00:45:49
longの読み書きについて質問失礼します。 @マルチスレッドで InterlockedExchange を使用し、longの値を変更しています。 A別スレッドで@で変更しているlong値を参照しています。 (読むだけの Interlocked〜 の関数が見当たらない為) この処理って大丈夫なんでしょうか? 実際にソースに組み込んでテストしているのですが、今の所大丈夫っぽいです。。。
volatile修飾すれば大丈夫という噂
共有リソースを元に、あるメモリに書き込みとかをしなければ問題ないよ。 参照だけなら、何の問題もなし。
Interlocked.Read
てv1か… Interlocked.Readは2からだったな…
>>461 InterlockedExchangeAdd
Pentium XE 840 ではHyper-Threading有効となっているので、 デュアルコア×2スレッドで4スレッド同時処理ができますが、 HTの論理コアを判別する方法はないでしょうか? SetThreadAffinityMask() を利用して1つのコアを スレッドに対して独占的に割り当てた場合にHT論理コアだと 処理速度向上が余り望めません。 もしくはWindowsでCPU番号(コア番号)が どのように割り当てられるかご存知ないですか? 単純に↓とか? CPU1-Core1-Main CPU1-Core1-HT CPU1-Core2-Main CPU1-Core2-HT Opteron だと? CPU1-Core1 CPU1-Core2 CPU2-Core1 CPU2-Core2
SetThreadAffinityMask(hThread,0x01); SetThreadAffinityMask(hThread,0x02); SetThreadAffinityMask(hThread,0x04); SetThreadAffinityMask(hThread,0x08); とした時にどのコアが使用されるか知りたいってことじゃねーの?
>>467 http://www.intel.com/cd/ids/developer/asmo-na/eng/269421.htm SetThreadAffinityMaskでCPUにスレッドを固定した後、
当該スレッド APIC ID を入手して core id と SMT ID を入手すればよい。
用語が混乱してるようだけど、Coreっていうのはホントのcoreのことで、
コアの中で演算回路等を共有して独立したCPU風に振舞うのはlogical
cpu とか SMT とか言う。
例えばDualCore でコアあたり2つのSMTをサポートするCPUの論理CPU構成は
Core1-SMT1 / Core1-SMT2 / Core2-SMT1 / Core2-SMT2 だ、
とこんな風に言う。
CRITICAL_SECTIONを使う場合ローカルなstatic変数として使用してもよいのでしょうか? ↓のような関数をスレッド内で呼び出す場合です。(ここではcountに同時アクセスしないようにすることを目的とする) int hoge(int init, int del, int i) { static CRITICAL_SECTION cs; static int count; if(init) InitializeCriticalSection(&cs); if(!init && !del) { EnterCriticalSection(&cs); count += i; LeaveCriticalSection(&cs); } if(del) DeleteCriticalSection(&cs); return count; }
>473 関数のセマンティクスとしてはクソだが、特に問題は発生しないだろう。
476 :
467 :2006/05/26(金) 20:21:43
>>472 なるほど…スレッドを固定してCPUIDでチェックすれば判別できそうですね。
用語解説は非常に勉強になりました。
ありがとうございますー
良く考えてみればSMT1が軽い負荷ならSMT2に重い負荷を
かけても遅くならないのかな…?
だとすると、同じコアのSMT1とSMT2に割り当てないようにすれば
効率が良さそうですね。
時期尚早な最適化は諸悪の根源だ
478 :
473 :2006/05/27(土) 00:41:46
>>476 みんなpthreadのデバッグってどうやってやってますか?
1ソースコードから処理を推測してデバッグ
2とりあえずなんでもいいからprintf仕込んでデバッグ
3gdbを利用する
4ツールを使って調査する。
もしいいツールとか方法あれば教えてください。
>>479 つ【5 - pthreadの気持ちになってみる。】
>>479 pgdbgはどうよ? (というかプラットフォームは何よ?)
Linuxは、IBMがpthreadを手がけた時に、
libpthdebug.aがAIXから持ち込まれるかと思ったが、
IBM版はlinuxサイドから拒絶されたので実現しなかった…
pgdbgですかぁ渋いですね それでいっちょ今から会社飛んでデバッグしてきますね
基本的に知識足りてねぇって感じなんですが質問させてください。 boostのmutexとconditionでWindowsAPIのEventと同等機能をやろうと思ってやってたんですが boost::condition::notify_oneを呼ぶときもmutexでロックしないとまずいですか? これがデッドロックせずに動くってことは多分そういうものだとは思うのですが… boost::mutex g_mutex; boost::condition g_cond; void Wait() { boost::mutex::scoped_lock lk(g_mutex); g_cond.wait(lk); } void Notify() { boost::mutex::scoped_lock lk(g_mutex); // これって必要ですか? g_cond.notify_one(); }
それでええで。 examples/libs/thread/example/condition.cpp 見てみ。
examples/は余分やな…
だめだ、pthreadが周りでどうしても落ちる セグ落ちでどうしてもダメううーん発見できん 神様助けてくれ
>>484 ありがとうございます、スッキリしました。
>>486 落ち始める直前の状態にまで戻して何やったのか胸に手を当てて考えてみれ。
ふっふっふっふ私はもうスレッドは怖くない スレッドの挙動を完璧把握する方法を知ってしまった ふっふっふっふ
490 :
:2006/06/01(木) 02:46:02
pthread_cond_timedwaitで、指定タイマーを経過しても待ち状態解除されず 停止したままになってしまっているのですが、引数パラメータに問題が あるのでしょうか。 gdbで確認したところ引数は問題なさげで、pthread_cond_timedwait内の pthread_sigsuspendで停止してるっぽいのですが…。
糞カーネルを使っているに一票
まずOSの種類とカーネルの素性晒せ
493 :
デフォルトの名無しさん :2006/06/07(水) 08:46:05
LINUXですよ(^^)
それは windows でない。とだけ言ってるに等しい
495 :
デフォルトの名無しさん :2006/06/08(木) 13:42:04
マルチスレッドとマルチプロセスでは一般的にどちらが効率的ですか?
タスク間のデータ参照が多いプログラムと少ないプログラムでは、どちらが「一般的」ですか?
volatileで回避できますか?
volatileとstaticで8割方回避できます!
なにをだ。
mutexとvolatileでは一般的にどちらが効率的ですか?
コーディング効率か コードの効率か で回答が変わってくる可能性がある
volatileはLockFreeで高速だが、アトミック操作に限定されるので、 一変数ならともかく、全体の整合性がどういう言い出すとプログラムは とっても面倒だし、バグがあるかないかの検証も面倒くさい
( ゚д゚)ポカーン
そのまま風邪引いて肺炎悪化させて死んでくれ
こんにちわ。誘導されてきました。 セマフォの扱い方について、よろしければ教えてください。 以下が環境です。 ・HP-UX & aCC ・共有メモリを使用し、その排他制御にセマフォを使用している ・共有メモリとセマフォは専用のクラスを作成して管理している ・上記資源は複数のプロセスで使用する ・上記管理クラスのインスタンスはプロセス内に複数存在する やりたいことは以下の通りです。 ・1つのプロセス内で、同じキー値を利用するセマフォの lock を ネストさせても2回目以降の lock で固まらないようにしたい ・unlock はネスト中の実際に lock した箇所に対応したところで 実行するようにしたい void a() { void b() { CSemafore sem1; CSemafore sem2; sem1.lock(); sem2.lock(); ←ここで固まらないようにしたい b(); sem2.unlock(); sem1.unlock(); ←ここで解除したい } } セマフォのクラスインスタンスが1つの場合は lock の回数を数えるカウンタを 用意することで解決できそうなのですが、複数の(同じキー値を利用する)インスタンスが 絡んできた場合に、上手に処理する方法が思い浮かびません。 こういったことは可能なのでしょうか。ご教示頂けると嬉しく思います。 よろしくお願いいたします。
trylockしてみて無理だったら待てばいいんじゃねぇの? 違うってかゴメンね
>>506 どういうデッドロックを想定しているの?
th1がaをlockしてbを得ようとして、th2がbをlockしてbを得ようとしているとか?
入れ子セマフォア
多重セマファオ
で解決できませんか?
>>508 >入れ子セマフォア
>多重セマファオ
おチツ毛
510 :
506 :2006/06/10(土) 19:05:08
>>507 ご返信ありがとうございます。
trylock とは「lock が可能な状態であれば lock を実行し、そうでなければなにもしないで
終了する」処理との理解で正しいでしょうか。trylock が失敗した場合の処理を実装できれば
よいのですが、出来るだけ単純化したいと考えており、今回の件では少し辛いです。すみません。
>>508 ご返信ありがとうございます。
知識が足りず「入れ子セマフォ」「多重セマフォ」の言葉が分かりません。
検索も試したのですが... すみません。
今回はスレッドを使用していないので基本的にはプロセス単位で考えています。
目的としては同一プロセス(スレッド)による lock でデッドロックを発生させないように
する方法を探しています。ご例示頂いた異なるスレッドによるデッドロックは‥‥実際にやって
いたのですがw、プログラムを直してうまく動くようになりました。
先の投稿に記述した「やりたいこと」について考えていたのですが、以下のようにすれば
出来そうに思えてきました。
・2つめの unlock 位置の判定の件は「カウンタ」の管理で解決できそう
(もっと良い方法があるようでしたらご教示頂けると嬉しいです)
・1つめのネスト時のデッドロック防止については、セマフォのキー値毎に最後に lock を
掛けたプロセス(スレッド)を識別出来るようにして、それが自プロセス(スレッド)で
ない場合だけ lock 処理を実施する
上記の「最後に lock を掛けた(sembuf.sem_op を 0 にした)プロセス(スレッド)を識別する」
方法はあるのでしょうか。お知恵を拝借できれば幸いです。
>>509 少しウケました。そのノリは高校の時以来です。w
>>510 ロックの話だけで頭がいっぱいになってるけど
そのsem1とsem2の間でどんな処理をするのか
教えてよ。
513 :
506 :2006/06/10(土) 21:59:59
>>511 ご返信をありがとうございます。
これは「多重セマフォ」の解説(使用例の項)でしょうか?
残念ですが、今回の件は同時参照を全て止める必要があるため、初期値を大きくすることに
よって解決とすることは出来ないと思います。情報をありがとうございました。
>>512 ご返信をありがとうございます。
不要と判断していました。たとえばですが。
共有メモリにある情報をまとめたテーブルがあるとします。
関数 SetData01() はこのテーブルの特定のデータを変更します。
同様に SetData02() など複数の関数があり、それぞれ関数内部でデータを変更するための
(受取手にとってわかりやすい形から格納に適した形への変換などの)処理を実施しています。
これら関数には対応する GetData**() も存在し、変更/参照時には共に排他制御(sem2)を実施します。
更に上記個別の値をまとめて取り扱う関数として SetGroupData() なる関数があり、
先の個別にデータを変更/参照する関数を内部で使用します。
この関数でのデータの変更時には、関連する全てのデータ更新が終了するまではデータ間での
矛盾発生を防ぐために他からのデータ参照を止めたい場合があるため、この関数の実行時にも
排他(sem1)を掛けたいと考えています。
回避策として、SetGroupData() で SetData01() などを呼ばずに自前で個別データの
設定を行う方法もあるのですが、少々煩雑な処理をするところもあるため、可能であれば
SetData01() などを利用する形に出来ればと思っています。
そのままのことは書けないため、説明が足りないところもあるかと思いますがご容赦ください。
>>513 そのよくわからんけど、SetDataなんちゃらっていうメソッドをいくつも用意するの?
そんなことするよりもさ
SetData(class data)を用意してこいつが責任もって共有データを単独で更新すればいいんじゃないのか?
じゃあ、みんなで同時に呼べねーべバーカとか思うなら、このSetDataは要求をスタックに貯めて逐次実行する
仕組みだけを排他制御で実装すればいいよね。共有メモリに置く程度のデータならそれぐらいで間に合わないかな?
515 :
506 :2006/06/11(日) 15:27:03
>>514 ご返信、ありがとうございます。
初めからそういう方向性を考えていれば...と後悔しているところです。(汗
次こそわ。
いや、変えないと今のも終わらないから。
517 :
デフォルトの名無しさん :2006/06/12(月) 17:52:57
質問です。 _beginThreadを使ってスレッドをつく、その中でゲームの描画をまわしているのですが void ThreadMain(void* pParam) { HANDLE hEvent = CreateEvent(NULL, FALSE, FALSE, NULL); DWORD dwLastTime = timeGetTime(); while(!pApp->m_bStopThread) { WaitForSingleObject(hEvent, 16 - __min(16, timeGetTime() - dwLastTime)); dwLastTime = timeGetTime(); //実際はここで描画をするけど、今は空. } CloseHandle(hEvent); _endthread(); } こんなことを行なうとタスクマネージャー上でCPUパワー使用率が100%近くになってしまいます。 (WaitForSingleObjectは、待機中CPUパワーを使わないとあったので期待したのですが) Sleepあたりを入れてみたりしても、Sleep(1000);くらい大きく指定しないと使用率0%付近になりません。 スレッドを使った場合、CPU使用率は高くなってしまうものなのでしょうか? 今まではスレッドを使わず、WinMainで処理をしていたのですが、そちらでは使用率が0%に近かったです。
518 :
デフォルトの名無しさん :2006/06/12(月) 17:53:43
今までスレッドをやらないパターンですとこんな感じでした。 CPU使用率は常に0%付近でした。 //WinMainに while(TRUE){ while(0 != PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE)){ if (!GetMessage(&msg, NULL, 0, 0)) return msg.wParam; TranslateMessage(&msg); DispatchMessage(&msg); } else if (16 <= timeGetTime() - dwLastTime){ dwLastTime = timeGetTime(); // 処理 } }
>>517 それ、WaitForSingleObject で待ってない(即リターンしてる)から。
他のスレッドが所有権を持ってないので、呼び出したスレッドが即座に所有権を得ておしまい。
2度目以降の呼び出しは、呼び出したスレッドがすでに所有権を持っているので即座に完了。
他のスレッドに所有権を持たせておくか、selectとかSleepでも使うべし。
520 :
519 :2006/06/12(月) 19:39:57
今思いついたんだけど、とにかくタイムアウトさせたいなら GetCurrentThread() で得たハンドルを wait してもいいのかもしれない。
>>519 アドバイスありがとうございます。
ただ、デバッガで追ってみましたところきちんと毎回Waitしている様子です。
Wait時間を分かりやすく5秒にしてみたところ、私の期待通りの動作をしているようです。
selectについてもこれから試してみたいと思います。
Sleep、WaitForSingleObject、いずれも、寝ている時間の精度自体は5msも保証できない
>>522 なんと、そうなのですか?
やはりFPS60なんていう精度を望む場合
Waitなんて無しでぶんまわしつづけるしかないのでしょうか?
(そもそも、Windowsで精密ゲームを作ること自体、Windowsの設計理念とは反している気がしますが)
524 :
519 :2006/06/12(月) 20:25:43
>>521 そですか・・・ところでメインスレッド側は PeekMessage 無しに戻しましたか?
単純に
>>518 から else 以降を取ってしまうと、CPU 100% のビジーループに
なるわけですが。
ところで、なんで、NOREMOVEでPEEKしたあと、またGetMessage呼んでるの? 単純に、直接REMOVEでPEEKして、Translate,Dispatchすればいいと思うんだけど
526 :
デフォルトの名無しさん :2006/06/13(火) 14:46:50
pthread_create() で作ったスレッドが終了したかどうかの確認は どうしたらいいんでしょうか? pthread_join() してしまうとその スレッドが終わるまで待たされてしまいますよね? やりたいことは、複数のスレッドを作って、作った側で pthread_t の配列にスレッド識別子を入れておき、それぞれがバラバラの 時間で終わるんですが、作った側で pthread_t の配列に入っている 値を元にそれぞれが終わったかどうかを確認して、終わっていたら それに対して pthread_join() をやって資源開放をて、配列の側も その部分を終了しているという値(たとえば0)にしたいんです。 (つまり UNIX で複数 fork() したあとで waitpid() の WNOHANG みたいにして何が終わったか、あるいは何も終わっていないのかを 確認するのと同じことです)。こういうのは pthread ではどうやる んでしょうか?
pthreadは詳しくないけど自分でフラグ作っても大して開発効率落ちないと思う。
SIG_CHLDシグナルで判断しろよ
>>528 pthread で作ったスレッドに対して SIGCHLD は使えないのでは?
子プロセスじゃないんだし。(Linux の実装だと使えるとか?)
POSIX P1003.1cにpthread_kill()ってのがあって、 signalを指定する引数に0を指定すると、 pthreadがいれば成功(シグナルは何も送られない)、 いなければESRCHのエラーになる。 processに対するkill(2)と同じ仕様。 > 自分でフラグ作っても大して開発効率落ちないと思う。 ではありますが。
>>530 あー! その手があったか。
くっそー。 pthread_kill() の man ページは見ていたのに気が付かなかった。
どうもありがとうございます。
スレッドのデバッグって何使ってますか? Linuxだとgdbだけかな?
知恵と勇気
>>533 そんなのいらねーよ何か教えねーと食うぞ?
「ちびくろ! おまえを たべちゃうぞ!」と、とらは いいました。
>>532 おれ、この前 gdb でやってみて大混乱。
使い方調べてから使わないといかんね。
無茶しやがって…
Windowsで、タスク内の複数スレッド間だけで通用する、高速な同期オブジェクトって無いですかね? なんか、どれもこれも、重そうで。
イベント系はユーザーモードで実行される。 イベント系はプロセス間の動機にも使えるという強みがある。 クリティカルセクションのみカーネルモードで実行される。 クリティカルセクションはプロセス間の動機で使えないがイベント系に比べると 非常に高速だという強みがある
ミューテックスとほぼ同じ。 タイムアウト指定ができなかったりする。
カーネルモードに移行するものが高速で ユーザーモードのまま実行できるものの方が遅いって?
544 :
539 :2006/06/25(日) 03:10:41
クリティカルセクションだと、スレッド間での排他は楽だけど、同期には使えないよね。 イベント系はカーネルまで落ちるし、プロセス間で使えるから重いよね。 同期に使えて、カーネルまで落ちなくても良いようなヤツが欲しいンだけど、 Windowsでは用意されてない気がするんだ。 それって、正しいのかな?
2つのスレッドだけでいいのならクリティカルセクションでも同期は取れる。 最初にどちらかのスレッドが所有権を保持するようにする。 片方のスレッドはEnter.....()で所有権が解放されるまで待機。 所有権を持っていたスレッドが所有権を解放すれば片方のスレッドは 実行が開始されるようになる。 高速性が大事でかつ簡易な同期処理でいいならこんな方法もある。 関数自作するとか。排他制御ができれば後は自分でいろいろできる。
Fiberでも使ってみたら? NT以降専用だが。
548 :
539 :2006/06/26(月) 17:26:10
>>548 具体的にどんな処理がしたいの?
単一プロセス内ならCriticalSection で何でも作れるよ
(だからこそOSもCriticalSectionしか提供してないわけで)。
あと「同一スレッド上では同期しないので」ってのはどういうことを
意図してるのかちょっとわからない・・・同一スレッドで非同期に
コードが実行されるのは Unix の signal のケースくらいで、
Windows のユーザモードでは起きないんじゃない?
>>549 ありゃ、そういう答えが返ってくると言うことは、
もしかして オレのCriticalSectionについて根本的な使い方や理解が間違ってるのかな…。
スレッドひとつしか無ければ、EnterCritical...をいくつ並べても無視されると思ってたんだけど、違うのかな…。
スレッドひとつならマルチスレッドじゃないからな
そんなにパフォーマンス気にしてるのに 何でロックファイルとかにいくんだ…
554 :
539 :2006/06/27(火) 22:53:13
>>551 でも、プログラムは大抵、ひとつのスレッドから開始されるんだよ。最初からふたつってわけじゃない。
まあ、だから、
>>545 は使えないんだよな。
なにか、壮大な勘違いをしている予感
まず、「同期する」をどういう意味で使っているのか説明してもらってからだな
同期の人と一緒に仕事をする 同期するじゃね?
>>539 そういうのは、ふつーにeventだの何だのをでも使ってみて、重くてやってらんなくなってから考えれば良い。
559 :
539 :2006/06/28(水) 14:26:16
>>558 なんだそりゃ。そう言う回答は勘弁して欲しいぞ。
なんで
>>539 は質問してる身分でやたらと偉そうなの?
リアルでもそういう質問の仕方しか出来ない人?
>>559 「回答」ではないだろう。
「重そう」と思うだけで実際にやってみることもせず
そのくせ「ロックファイル」なんて単語まで飛び出し
結局何がしたいのか、「同期」が何を指しているのかも
説明してくれない君への
アドバイスじゃまいか。
おまえら馬鹿なんじゃね?
つーか、時々デッドロックするようなプログラムしか作ってないのかょ、おまえらは。
なにか、壮大な勘違いをしている予感
なにかが気に喰わなくて暴れ始めたお母ん
予感でプログラムが組めるヤツはニュータイプ。
まてまて。
>>539 はWindows のカーネルやAPIを設計した人たちや
普段からマルチスレッドAPなんかさんざ書いてる漏れも
見落としている、何か難しい問題に対処しようとしてるんだよ。
それはたぶんロックファイルと関係のあるなにかなんだろう。
漏れには想像もできないが、頭ごなしに否定しないでだまって
観察してあげるべきじゃないか?
なにか、壮大な勘違いをしている予感
Vistaから同期IOのAPIがキャンセル可能になるそうですね!
それは、非同期IOのことだろ。
>>573 同期IOだよ。非同期IOのキャンセルならWindows98でも出来る。
それを非同期というのではないのか?
>>575 いや、絡んでるつもりは全くなかったんだ、すまん。
つまり、同期I/Oを他のスレッドで実行することによって擬似非同期I/Oの
ような使い方をしたときに、そのAPIの実行をキャンセルすることができる
ようになったということだな。
同期/非同期とはそういうことだったのか。勉強になった。
579 :
デフォルトの名無しさん :2006/07/01(土) 17:16:56
Linuxのカーネル層でマルチスレッドのような 設計が必要になっているんですが、 Aという関数が終わったらBの関数で 止めていたところが動き出すような設計って どうやったら良いもんですか? セマフォを使った排他処理ってデータに 対する排他処理になると思うんだけど、 そういう形で発想の転換をしないと駄目なのかな?
待ちたいところでスピンロックでもasm WAITでもなんでもしておけばいいだろう
>>579 condは適当に初期化。
A() {
〜;
pthread_cond_signal(&cond);
return;
}
B () {
pthread_cond_wait(&cond);
〜;
return;
}
>>581 参考になります。
これってAのreturnの直前でBが動き出す
ということですよね?
Aが終わってからってのはやっぱり難しいのかな。
>>582 AA() {
A();
pthread_cond_signal(&cond);
return;
}
>>522 昔の奴へのレスで恐縮なんだがWindowsのSleepってそんな精度悪かったっけ?
::timeBeginPeriodとか使っても駄目?
他に忙しく仕事をする連中が居なければ、だいたいは大丈夫かもね。
>>585 なるほど
まあそれほど信用できないってことか。
スレッドの教科書ってどんなのあるの? アルゴリズム系に強いやつが欲しい
OSによって違うな。
pthreadなら>>1-
>>9 辺り見て。
Lamport's bakery algorithmとかさこんな古典的なやつから 今の新しいアルゴリズムまで載ってるのないのか.....
>>583 AAは別の人のソースなので手を加えられないのです。
でも参考になりますた。
ありがとうございますた。
windows には win32 API で色々なイベントを使えるようになってますが、 UNIXではpthreadのイベントを使う以外にないのでしょうか?
593 :
デフォルトの名無しさん :2006/07/05(水) 10:16:26
Winsock、_beginthreadで起動して、 グローバル変数で終了要求するような、 簡単なスレッド書いているのですが、、、。 スレッド内でrecv()のような、 ブロックするような関数を呼びたくなりました。 これを終了するにはどうしたらよいでしょう。
ソケットオプションでノンブロッキングにすればいいんでない?
595 :
デフォルトの名無しさん :2006/07/05(水) 11:33:24
594> ありがとう、そうします。 一般的にはどうでしょ? ブロッキングするような関数をスレッドで呼んではいけない?
ブロッキングするべき状況と、そうでない状況がある。 前者ならブロックさせとけばいいし、そうでなければ非同期APIを使うか、 別個にスレッドを作ればいい。
>>593 recv()呼ぶ前にMSG_PEEKしておくなりしとかんとあかんよ。
#つーか、TCP受信処理を途中で終わらせると言う仕様そのものが如何なものかと。
>>595 一般的かどうかは知らないけど、普通はselect使うんじゃないかな。
599 :
593 :2006/07/05(水) 13:49:40
>>596 「強制終了」以外は普通にブロックして、データが届いたときだけ
処理してくれればいいんだけど。って状況でした。
非同期っていうと、WSAEventSelect, WSAAsyncSelectで、通知を待つって
ことでよいですよね?
>>597 ちょっとわかんないのですが、
MSG_PEEKで、受信データが無いときはどうやって次の受信データを待つのが綺麗?
あと、途中で終わらないとしたら、どうやって終わるのがよいですか?
>>599 WSAAsyncSelect(s, hwnd, 0, 0);
shutdown(s, 1);
while (recv(s, buf, buflen, 0) != 0) {}
closesocket(s);
>>600 それ先方がデータ送ってくれないとCPU100%のビジーループ。
サーバアプリでは非常によろしくないコーディング。
recvって、ブロックするんじゃないの?
スマソ。ノンブロッキングのソケットと勘違いしてた。
WSAAsyncSelectした時点でノンブロックになる
605 :
593 :2006/07/06(木) 17:50:25
任意のタイミングで終了させたいスレッド内では、ブロックする関数は呼ぶな。 socketはデフォルト非同期で。 で理解しました。 ありがとう。
>>605 そう理解したんならそれでもいいが・・・
ソケットを任意のタイミングで終了させると再起動したときにわややがな。
608 :
593 :2006/07/06(木) 23:34:44
>>607 どゆこと?
例えばサーバ的なアプリで、その受信用スレッドを、サーバ的なアプリ
のユーザ都合でブチっとしたくなった場合、、、
受信処理を終了させて、クローズなり何なりをしたい。
そんな場合ですが、再起動とは、ここでサーバ的なアプリを再度起動して
受信を始めようとした場合になにかが起こるってことですか?
下の層が受信しているのにアプリが落ちたら、次に起動するときにbindErrorになる。
つかさ、断片的な情報を積み重ねて信頼性のないアプリ作るよりさ、 ばしっとWinsock Programmer's FAQとか、Winsock関連書籍を読み とおして、きちっとしたアプリを作ろうとは思わんのかね。
>>609 アドバイスするなら、その前にFAQくらい読んどけよ。
知識足りなさ過ぎ。
612 :
593 :2006/07/07(金) 10:11:03
>>610 終了するときは、shutdown(sock, 1) をスレッドの外から呼べ、
そうするとrecvが0返すので、スレッドを抜けろ。
で、理解しました。ありがとう。
>>609 100%賛成して同意して応援します。
他人のいう事に惑わされたりマニュアルやFAQを読んだりせず、
先方が送信を続けている間は終了できないプログラムを作り続けてください。
>>593 fcntl(s, F_SETFL, O_NONBLOCK); って使えない?
(Windowsだとこれはないのかな?)
>>595 select() 使う場合は他のスレッドが同じソケットから読まないように
作る必要がある。recv() ではあまりないかも知れないが、サーバ用に
bind() した一つのソケットに対して複数のスレッドから accept()
する場合にselect()使うとハマる(2つ以上のスレッドがselect()を通過
した場合に一つのスレッド以外がブロックする)。防止するには上に
書いたような fcntl() で O_NONBLOCK セットして accept() で止まら
ないようにする。
>>609 最初に setsockopt() で SO_REUSEADDR をセットしとけばいいんじゃないか?
615 :
デフォルトの名無しさん :2006/07/08(土) 02:08:08
volatile最強
メモリモデル勉強しる
617 :
593 :2006/07/09(日) 20:09:28
最後にもひとつ。 一般的に、マルチスレッドで使われることを前提にした、受信待ちのような ブロックする関数を提供しようとした場合は、それと一緒に受信を中断 して安全に返るための、他のスレッドから呼ばれる関数(socketの場合のshutdown) を提供すればよい。 ですか? 他に綺麗な方法あったら教えてください。
一般的には、recvでブロックさせるのではなく select系でブロックさせて selectをブレークさせる方法を使うだろ。 つまり「外部から解除できないブロッキング関数ではブロックさせない」と。
selectってキャンセル可能だっけ
selectで同時にパイプを待ったり WSAEventSelectで同時にEventを待ったり というやり方のこと。
selectでtimeout設定すればいいと思うけど それとももっと高度な制御がしたいの?
>>621 timeout 値の設定がめんどい。
仕方なく
>>620 の WSAEventSelect 使ってるけど、
これはこれでめんどい。
pselect
624 :
593 :2006/07/10(月) 10:22:26
>> 618 なるほど。 Linuxでは、読み込むものは全部ファイル(ファイルデスクリプタ)で、 中断など例外的な処理は全部シグナル。と思ってpselectで綺麗にい けていたんだけれど、 Winにいったら、いろんな方法がありそうだけれど、どれもいまいちに見えて。。 WSAEventSelectは、socket以外にも汎用的に使ったりする?
>>617 スレッド(タスク)開始、実行状況(実行結果)の取得、完了待ち、中断のための関数を
それぞれ提供するのが一般的だと思います。
あと場合によっては先方のスレッドでコールバックされる実行状況の通知のための
コールバック関数なんかも設定できると UI 作るときには便利(プログレスバーとか)。
>>624 個人的な意見だけど、Windows では(ソケットなら WSAEventSelect等も使って)
(Msg)WaitForMultipleObjectExで待機、何かあれば処理するというのがマルチ
スレッドの場合の定石だと思います。
ソケットだけ相手にするなら単にclosesocketしてしまうというのもアリだと思うけど。
>WSAEventSelectは、socket以外にも汎用的に使ったりする?
ソケットを相手にしないのにWSA〜を使う局面は無いと思う。
>>624 Winでも sock をファイルとして扱えるよ。
Linux (Kernel 2.6.17) で、pthread_create() で複数スレッドを作り、 そのスレッド全てが同一の bind(), listen() されたソケットに対して accept() を行うプログラムを作ったのですが(O_NONBLOCKなソケット ですが)、クライアントプログラムから複数 connect() すると、 accept() が同じ値のファイルディスクリプタを返して来ます。処理を 単純に書くとこんな感じです。 for(;;) { int cs = accept(...); // ここで cs が別スレッドと同じ値になる。 if (cs == -1) { if (errno == EAGAIN) { usleep(50000); continue; } else { break; // error } } else { proc(cs); // cs を使った処理。 close(cs); } } accept() の前後に pthread_mutex_lock(), pthread_mutex_unlock() で ロック、アンロックをしても同じでした。 これって Linux のバグなんでしょうか? これを回避するにはやはり accept() をするスレッドを一つにしないと 駄目ですか?
628 :
デフォルトの名無しさん :2006/07/18(火) 19:04:29
すいません。質問なのに age 忘れました。age ておきます。よろしくお願いします。
わざわざageんなよ
コンパイル・リンク時のコマンドライン見せろ
>>627 > accept() の前後に pthread_mutex_lock(), pthread_mutex_unlock() で
> ロック、アンロックをしても同じでした。
この時点でプログラミングの問題じゃないことに気付け。
>>627 >これって Linux のバグなんでしょうか?
つかその前に、どこで習ったんだそんな阿呆な手順。
acceptしてからthreadおこせ
>>630 gcc hoge.c -lpthread
>>631 どういう意味ですか? 同時に複数のスレッドが accept() しないように
しただけですが?
>>632 これは阿呆な手段ですか? 何故? その辺詳しく教えてもらえますか?
どこで習ったかは記憶にありません。ただ昔 Java で似たようなものを
作った時はちゃんと動いたと思いました。
>>633 それはつまり accept() は親(?)スレッド一つでやるということですね。
636 :
デフォルトの名無しさん :2006/07/19(水) 10:02:36
accept()を排他しても、 そのプログラムがまともにうごかん事に疑問はないのか? 他の部分がおかしいだけではないのか?
>>636 そこが疑問ですよ。なんで既に取得してオープンされているファイル
ディスクリプタと同じ値のファイルディスクリプタが返って来るのか
という点がね。
気になるのは Linux の場合スレッドは clone() システムコールで作った
特殊な別プロセスであるということです。別プロセスだから複数スレッドで
accept() した時に同一ファイルディスクリプタが取れてしまうんじゃない
かな、とは思ったんですが、確証がなかったので質問したんです。
(Linux板の方で質問した方がよかったかな? でも他のOSではこういうのは
できないのかも少し気になる)。
で、その後、accept() を一つのスレッドでだけやって、他のスレッドは
待機させておいて、accept() 成功後にファイルディスクリプタを待機
スレッドに渡すように作り替えたらちゃんと動くプログラムは作れました。
理由はどうあれこういう風にするか、あるいは accept() 成功後にスレッド
作るように書かないと駄目なようですね。
>>627 > int cs = accept(...); // ここで cs が別スレッドと同じ値になる。
本当にこれと同じ書き方だったんだな?
csが大域変数だったってオチがありそうだ。
>>638 いいえ。大域ではありません。autoです。
生半可な学習しないで、ファイルディスクリプタについてちゃんと勉強したら?
>>637 >スレッドは clone() システムコールで作った
ちょwwwwおまwwwww帰れwwwww
げ、pthread_createで作ってんじゃないのか・・・!!!
>>640 生半可? どの辺がですか?
>>641-642 pthread_create() で作ってますよ。clone() は内部動作の話です。
こいつむかつく〜☆
>>643 コンパイルオプションとかはどうだろう・・・ -pthread とか付け忘れありませんか?
>>646 -lpthread だけ指定して -pthread を指定していないのではないか、といっているのだが。
>>648 -pthread は指定していませんでしたが、man ページや info 見ると
Linux では関係ないようですよ。
念のため指定してテストしてみましたが、同じ動作になりました。
いい加減、誰かファイルディスクリプタの説明してやれよw
>>647 そっちの方がいいですか?
スレッドとネットワークと Linux が混ざった疑問なのでどこがいいのか迷ったんですが。
>>640 >>650 pthread_createで作ったスレッド間では、ファイルディスクプリタは共有されます。
すなわち、同じ数値=同じソケット端点。
何がいいたのか知らんがこれでいいか?
>>651 どっちがいいのかはわからんけど、このスレじゃ解決できなさそうじゃん。
Linuxのスレッドが特別なプロセスだったのは、2.4より前の話だよ。
# 例えばpidやsignalの扱いなど。
>>627 は、2.6.17だから関係ない。
>>637 > accept() 成功後にスレッド作るように書かないと駄目なようですね。
そんなことはない。
>>652 それは知ってますよ。だからこそOSがおかしいんじゃないかと思ったんですから。
元々の質問を要約すると、まだ close() されていないファイル
ディスクリプタの値を accept() が返して来るのは何故かです。
一つのスレッドが accept() で 5 を受け取ったとして、それが
close() される前にもう一つのスレッドが行った accept() が
受け取ったファイルディスクリプタの値も 5 だったということです。
これ、accept() を一つのスレッドでしかやらなければ当然 6 などの
違う値が返って来ます。
>>653 今のところそんな感じしますね。
>>658 そこはたしかに近いこと話し合われてたスレですね。
じゃあそこに移転します。
こちらのスレのみなさまありがとうございました。
660 :
636 :2006/07/19(水) 23:13:46
な?
うはwww ボッコボコwww しかも自分のミスwww
File Disk Riptor 略して FDR である
なんか車の駆動方式っぽい略称だな。
665 :
627 :2006/07/20(木) 16:04:12
申し訳ありません。私がバグっておりました。 accept() 後の処理を別関数でやっていたのですが、その中で fdopen() を使って accept() で受け取ったファイルディスク リプタから FILE * を作って fgets() や fprintf() を使って いました。それでその関数から返る直前に fclose() をして いますが、そうすると当然元となったソケットも close() されます。 このことをすっかり忘れていたためこの別関数から戻って 来ても accept() で取ったファイルディスクリプタは オープンしたままだと思い込み、別関数から帰って来てから close() までの間に別スレッドで accept() した時の ファイルディスクリプタと同じ値になることがあったため、 今回の疑問に繋がっていました。 ということでお騒がせしました。 Linux でも複数スレッドからの accept() は問題無くできます。
まあせいぜい地雷原を走り抜けてくれ
この人の場合、さらに non-blocking にしてあって、ブロックしないでポーリングしてるらしいよw
>>667 > 特にメリットも思いつかないので、
はあ
試したことはないが、 複数のThreadがServerSocket#accept()でブロックされてるとき、 ブロック解除で起こされるThreadはたぶん唯1つなのがメリットじゃないかな。 単一のThreadがaccept()待ち→ブロック解除→Queueに放り込んでWorker Threadを たたき起こすパターンだと、Queueを監視する複数のWorker Threadがいったん たたき起こされるから。
672 :
デフォルトの名無しさん :2006/07/26(水) 17:24:59
お世話になります。 識者のご意見ください。 以下のような状況です。(環境はVC6のWin32API) メインスレッドAと、待機スレッドBがあります。 BはSuspend状態です。 あるタイミングでAがBに仕事を投げてResumeしました。 Bは仕事が終わったら自分でSuspend状態になりたいのです。 Bは自分のHANDLEをSuspendThreadしちゃってもいいものでしょうか? AがBのフラグを見てSuspendしてやるというのはちょっと効率が 悪い気がします。 以前はBを待機スレッドではなく、その都度生成して自殺させていました。 が、この方法だとデバッグウインドウに生成と消滅のメッセージが 出まくるのと、やはりCreateThreadの負荷が気になります。 こういう場合の常套手段など、ご教示ください。 待機スレッドがCPUを食わないようにするために、Suspend状態に しておく、という風に考えるのは変でしょうか? よろしくお願い致します。
>>672 ただのワーカースレッドでええんちゃうかと
マイクロスレッドのようなものを考えてるなら、ファイバでも使えばいい
>>672 自分をSuspendするのは悪くない。というか、それが唯一のSuspendThreadの正しい使い方。
基本的には自スレッド以外をSuspendThreadしてはいけない。
ただし、普通はautoresetのイベントハンドルを用意して WaitForSingleObject で待たせておき、
SetEventで起こす。これはAがBをResumeThreadで起こすのが難しいから。
具体的には、SuspendThread/ResumeThreadで待機を実現しようとすると、
ResumeThreadするときに、ちょうどBが何かの仕事を終えてSuspendThreadする
直前だったりするとResumeしても即Suspendしてしまうので、これを避けるために
クリティカルセクションとフラグが1つ余分に必要になってしまって効率も悪いし
コードもムダに複雑になる。
みなさん、レス有難うございます。
>>674 >autoresetのイベントハンドルを用意して WaitForSingleObject で待たせておき
こんな感じでしょうか?
スレッドB{
while(1){
WaitForSingleObject(XXX);
何か仕事(B*)
}
}
スレッドA{
while(1){
何か仕事の準備(実行中のB*の部分を触らない配慮はしている)
SetEvent(XXX);
}
}
>直前だったりするとResumeしても即Suspendしてしまうので
なんとなく現象の心当たりがあります。
>>675 Bが待機するところはそんな感じです。
あとまぁよく使うパターンとしては
(1) AがBの仕事の完了を待たずににいくつもの仕事を投げておけるようにQueueに仕事を登録して SetEvent する。Bは起こされたら、Queueにある仕事を全て実行してからWaitする。
(2a) 「仕事終わったよイベント(初期値はON)」ってのも用意して、Bが仕事を終えたらSetEventする。Aは仕事終わったよイベントを待ってからBを起こす
(2b) CreateSemaphoreでMaxCount 1 のセマフォを作って、AはWait,→仕事の準備→ReleaseSemaphore、
BはWait→仕事を取り出して実行→ReleaseSemaphore とする。
仕事が終わったかどうか知りたくなることも多いので、漏れは2aのパターンを多用します。
殆ど等価な 2b でもいいのかも知れない。
>>676 Suspend,Resumeでやってたところを待機オブジェクトにしました。
すっきりした感じがします。
>(2a)
なんとなくこれっぽいことはやっていました。
どうもありがとうございました。
lock-freeについて調べている内に CAS(CompareAndSwap)という概念にたどりついたのですが ちょっと教えてください。 /* 関数内の処理はatomicに処理されると仮定*/ bool CAS(void*addr,int expval,int newval){ if(*addr == expval){ *addr = newval;return true; } return false; } *addr=0; while(!CAS(addr,0,*addr + 1)){ //※ここでコンテキストスイッチ } //アトミックにインクリメント成功? 例えば※の部分で別スレッドがaddrの値を5に変更→0に変更 という動きをした場合、*addr == expvalが成り立ってしまい、 インクリメント成功とみなされてしまう気がするのですが・・・ 何か回避策等あるんでしょうか。それとも俺の理解不足なんでしょうか
>>678 「アトミックなインクリメント」というものを理解していないような気がする。
過去に5だったかどうかはさておき、他のスレッドで0にされたものが1に
なるのだから成功している。
というか5で放置されてて6になってもやはり成功。
*addr=0;
IntgerlockedIncrement(&addr); ←APIによるアトミックなインクリメント
などとしたところで、この2行の間に*addrが5になって0になることもある。
「アトミックなインクリメントに失敗」というのは、2つのスレッドで1度ずつ
アトミックなインクリメント操作が行われたにも関わらず2増えないことを言う。
これは正しい実装では決して起きない。
追記: CASによるアトミックなインクリメントの実装は、正しくは↓ while (!CAS(addr, *addr, *addr+1) {}
681 :
678 :2006/07/27(木) 21:49:17
とりあえず、CAS(xxx, *addr, *addr+1) なんて書いている奴は氏んでいいよ。 atomic_inc(int *addr)は do { int var = *addr; } while (!CAS(addr, var, var+1)); にしないと。 まあ、複数のスレッドで勝手に値をセットするような変数を 特定の個所だけatomic_incを使っても意味は無いがね。
終わった話題についてなにを得意げに語ってるんだろう…。
つまり、「ほんと、バカしかいないんだね」ってことか。
やーい ばかー
volatileですべて解決!
>>682 バカは喪前のほうだと思うが・・・
なぜ自分がバカなのかが知りたかったら、
元のコードの問題点を書いてご覧よ。
書いてるうちにわかるだろ。
元のコードの問題点は関係なくて *addrを2度読み出して同じ値が取れると思っているのがバカだって事だろ。
しかも、この手のバグは非常に表面化しにくく 再現性が低い(デバッグが難しい)。
volatileですべて解決するという忠告がみえないのか?
別CPUから発言が見えるようになるまでには時間がかかります
693 :
デフォルトの名無しさん :2006/07/29(土) 18:15:53
VC++とMFCでマルチスレッドなサーバープログラムを書いています。 サーバープログラムを終了する時、ソケットが走ってるスレッドを終了させないといけませんが、 スレッドに終了を通知する手段が分かりません。 どのように終了を通知するのか教えていただけないでしょうか。 よろしくお願いします。
ソケットをどういう風に使ってるかによると思うけど、イベントとか単なるフラグとか。
>>693 ExitProcessで自殺すればおk
696 :
693 :2006/07/29(土) 19:49:37
CAsyncSocketを継承して作ったUDPのソケットです。 クライアントからやってくるパケットをRecvFromで受けて、データに応じてSendToしているだけです。 現在、スレッドを閉じるのにdeleteでデストラクタを呼び、強制的に終了させているのですが デバッガで追っかけていくとCAsyncSocketの中でエラーが発生します。 詳細は不明ですがおそらくソケットを閉じずに終了したためではないかと思います。 Win32APIでマルチスレッドなプログラムを組んだときはPostThreadMessageで終了メッセージを 送って、WaitForSingleObjectでスレッドが落ちるのを待っていたのですが、MFCで そのような手順を踏んだ終了の仕方は(強制終了じゃないやり方)ないのでしょうか?
CAsyncSocketて使ったことないから知らないけど、 非同期に通信してるなら終わりにするかどうか判断する機会はあるんじゃないの?
CAsyncSocketのデストラクタが動けば万事OKみたいなことMSDNには書いてあるけど。 スレッドを強制終了するから、そのスタックにあるCAsyncSocketがリークしてるとか、 そういうこと?
699 :
693 :2006/07/29(土) 21:12:35
>>697 複数台の設備との通信をするサーバープログラムなのですが、設備のON/OFFとサーバーのON/OFFは
必ずしもリンクしていません。一応作業標準として順序だてることは可能ですが、予想外のトラブル(瞬停など)を
考えると何かのパケットが来たらソケットを閉じてもいいとはできません。
サーバープログラムを閉じる作業中にソケットが走っているスレッドに終了を通知できればいいのですが
その方法がわからないのです。
>>698 >そのスタックにあるCAsyncSocketがリークしてるとか
そのとおりです。
スレッドが終了する時のイベントハンドラで CAsyncSocketをdeleteじゃダメって事?
>>700 今はスレッドのデストラクタでCAsyncSocketをdeleteしていますが、その中でエラーになります。
702 :
デフォルトの名無しさん :2006/07/29(土) 21:38:00
ねぇ。マルチスレッドって何?
multi 【名-1】 (複数{ふくすう}の色調{しきちょう}からなる)縞模様{しま もよう} 【名-2】 マルチビタミン(錠剤{じょうざい}) thread 【名-1】 (繊維を束ねた)糸、より糸 【名-2】 糸[繊維]状のもの、細い筋状のもの 【名-3】 (全体をつなぎ止める)筋、(話などの)脈絡{みゃくらく}
704 :
デフォルトの名無しさん :2006/07/29(土) 21:53:15
縞模様の筋ですか?
筋肉のことですか?
>>691 まさかとは思うけど、本気で言ってるわけじゃないよね?
707 :
デフォルトの名無しさん :2006/07/30(日) 00:24:25
>>689 だって別に同じ値じゃなくても問題ないんだよ。
単にその1度のCAS呼び出しがfalseになるだけ。
>>707 第3引数の *addr + 1 を評価した後に別スレッドによって *addr の値が変更され、
その後に第2引数の *addr が評価されるとアウト。
>>701 スレッドを強制終了させないで、外部から何かきっかけを与えて自分で終わるようにすればいいだけじゃん。
>>691 >>707 >>708 の言うように、
「CASの第2引数の値」と「CAS呼び出し時に*addrに入っている値」
これが違うのは問題ないが
「CASの第2引数と第3引数の値の差」が1でない場合に誤動作する。
コンパイラの最適化で読み出しが1回になるケースもあるだろうが
最適化オプションで動作が異なるのはデバッグを難しくするだけ。
volatileを使えば、読み出しが2回になることが保証されるだけ。
一般的な双方向リストをマルチスレッドで使うとまずいですか? new -> next = next; /* ここでスレッドが切り替わるとか? */ new -> prev = next -> prev; みたいな事が起きるとうまく繋げないような気がします。 WinAPI を使ってオブジェクトかなにか?を作って排他制御する 必要があるのでしょうか?
712 :
デフォルトの名無しさん :2006/07/31(月) 13:41:09
問題ないw
>>711 まずい。複数スレッドからappendすると、ノードが行方不明になったりする。
ただ、スレッドセーフな双方向リストにするより、
外部の同期オブジェクトを使ってそのリストへのアクセスを同期化する方が
柔軟。
volatileですべて解決!!!
この話では無理w
716 :
デフォルトの名無しさん :2006/08/01(火) 11:20:51
>>711 問題ない
関数内ではスレッドの切り替えは起こらない
preemption はいつでも起こりうるでしょ
718 :
716 :2006/08/01(火) 12:39:23
起こらないでしょ
ようやくWindowsのメッセージディスパッチのことを理解したばかりのヒトが それをマルチスレッドだと思い込んでるんでしょう。
>>716 は、ユーザレベルスレッドしか使った事無い人なんでしょうかね。
実装がユーザレベルかカーネルレベルかと、プリエンプティブかコ・オペレーティブかは関係ないだろ。
関数内では起こらないってのもすごいよな。 普通は全てmainの関数内なんだが。 まあWndProcはまた別だが、それもWinMain内ででGetMessageしてるわけだし。
725 :
716 :2006/08/01(火) 14:35:50
反省^^
>>723 そこに異論は無いけど、言いたい事は分かるでしょ。
まあ、あれだ。がんがりたまえ(笑)
728 :
デフォルトの名無しさん :2006/08/02(水) 12:46:56
一般的なのはミューティックスを作る方法なの?
ディスクトップでディスクリプタをミューティックスで保護することを考察
むてふ
ティキストエデタ
732 :
デフォルトの名無しさん :2006/08/02(水) 15:05:17
www
ヴォラタィル
コンピゥタァ
736 :
デフォルトの名無しさん :2006/08/03(木) 14:38:59
static bool g; if (!g && g = true) {} この if ()の中でスレッド切り替えって起こります? 排他処理になりませんか?
>>736 その g = true というのは本当に g = grue なのか?
それとも g == true の書き間違い?
あ、俺も書き間違えた。すま。
>>736 > この if ()の中でスレッド切り替えって起こります?
起こる
> 排他処理になりませんか?
ならん
740 :
デフォルトの名無しさん :2006/08/03(木) 18:52:39
w
ちょっと待てよ。C言語だとするとショートサーキットだよな? !g の結果が false なら g = true は実行されないよな。 true なら実行される。 排他になるんじゃないか?
ひょっとしたら !g がアトミックじゃない処理系もあるかも
ショートサーキットは関係ない。 !gの評価と、g=trueの間にスレッドが切り替わる可能性があれば、排他として役に立たない。
アセンブラレベルで考えるんだ
なんだろ? 書き込み見てると、CPU命令レベルでの挙動に思い至らないのが居るな。 ソースレベルの字面で捉えてコンパイルというのが何なのかまったく知らないよう に思える。 こんなんで日本のプログラマーのレベルは大丈夫なのか? 小中学生だったら 知らなくても無理は無いのか。
アセンブラまで降りる必要は必ずしも無いとは思うが メモリの読み込みと書き出しを同時(atomic)に行うことは (普通は)出来ないということくらいは知っておく必要がある。 もちろん、プロセッサはそのための命令を(普通は)用意しているが コストがかかるため、普通にソースを書いた場合 コンパイラはその命令を使ったコードは出力しない。
えらそうに講釈たれてても > 同時(atomit) この一言で台無しだな。
必死な子がいるなぁ。
>>747 別のプロセッサに割り込まれないように
lock等で保護してからxchgしたりincしたりnegしたりするけど
それをatomicと言わないとでも?
例えばあるメモリの内容を+1する場合、
「+1する命令をメモリに対して発行する」ではなくて
「プロセッサがメモリを読んで、+1した値をメモリに書き込む」だし。
なに一生懸命説明してるの? これスレでそんなこと知らない奴なんてあまりいないよ。 俺はただ「atomic」と「同時」って全然違うって言いたいだけなんだが。 まあ俺も atomit とか書いてるようじゃ人のことは言えないわな。(w
最近なりを潜めてる、某キティと文体が似てる・・・
読むのと同時に書かないと壊れるメモリもあるだぜ?
「atomic」は日本語で言ったら「不可分」ちうことですわ。
原子力って感じかと思ってた
分割不可能な最小単位つうことですょ
つまり、鉄腕アトムは分割不可能と言うことで宜しいか。
「atomic」には他に「原子の」みたいな意味もあるんですわ。 昔は原子(atom)は物質の不可分な最小単位と考えられていたので。 どっちの意味が先か知らんけどね。
で、何が言いたいんだ?
atomic bomb 分割不可能な爆弾
割ったら被爆しちゃうからね
>>761 誰でも知ってるような事をちょっと偉そうにしゃべくってみたかっただけですわ。
被爆と被曝
>>760 なに一生懸命説明してるの?
これスレでそんなこと知らない奴なんてあまりいないよ。
「同時」って書いちゃうヤツ以外はね。
VRAM(昔のやつ)やWRAM(初代Milleniumが採用した奴)を思い出した。
>>768 どこが変なのか未だにわからんのだが?
「読み込みと書き込みが同時に出来ない」
だから
「読み込みと書き込みをatomicに出来ない」(バスロックしなければ)
という意味なんだけど?
>>764 俺は知らなかったからタメになりましたよ
一応ありがとう
この流れ見て、コンカレントとパラレルの違いが理解出来なかった当時を思い出した
既に「atom」という言葉があるからこそ、物質の探求の過程で原子にその言葉を当て嵌めたってことくらい >758を理解していたら考えるまでもないだろ。
>>770 同時(simultaneous)と、不可分(atomic)の違い。
意味が分からねえ・・・
ガキ共の言葉遊びここまで
じゃあ今から大人の言葉遊びか・・・エロス
779 :
736 :2006/08/04(金) 13:14:37
if (g = g ? false : true) この場合でも排他にならない?? アホですまん
C言語のレベルでどの式がアトミックになるかという事に依存するのが間違いだと思う。 現存する全ての環境でアトミックに実行されるような式でも、それは処理系依存。
その後、原子は分割可能であることが判明してしまいました。
陽子と電子に分割できるんだっけ?
あと中間子
それらの素粒子も実は更に…… つーのはやめておこうか。
mkdir() は atomic らしい
787 :
779 :2006/08/04(金) 14:38:19
リスト処理でつなげるときに排他したいけど WinAPI使うしかないみたいですね
>>779 もう諦めて、素直に同期オブジェクト使いなさい。
mutex使わないのはなぜですか
Windowsでプロセス内だけでいいならCriticalSectionのほうが速いんじゃなかったっけ
>>787 それならCriticalSectionで十分
>>787 これもAPIになるけど、InterlockedCompareExchangeとかでも自分でロックを作れる。
ただ、CriticalSection使うほうが簡単でおすすめ
>>755 > 読むのと同時に書かないと壊れるメモリもあるだぜ?
kwsk
それはリフレッシュのことかね。
「メモリなどの外部デバイスに対して複数の入出力をatomicに行うには同時にやるしかない。ロックしないならば」 という文章があったとします。 この文章の最後を無視して 『メモリなどの外部デバイスに対して複数の入出力をatomicに行うには同時にやるしかない』 だけを引用して 「ロックすればいいじゃん。バカじゃねーの?」 と書き込むのは、とても恥ずかしいですね。 では、前半部も無視して 『atomicに行うには同時にやるしかない』 だけを引用し、 「同時とatomicは違うだろ。バカじゃねーの?」 と書き込むのは、どのくらい恥ずかしいことなんでしょうかね。 まあ夏休みだから、「こくご」の能力がちょっと不足している人が現れるのも 仕方ないかもしれませんが。
746 名前:デフォルトの名無しさん:2006/08/03(木) 23:05:44 アセンブラまで降りる必要は必ずしも無いとは思うが メモリの読み込みと書き出しを同時(atomic)に行うことは (普通は)出来ないということくらいは知っておく必要がある。
>>797 ロックすれば、読み込みと書き出しを同時に行わなくてもatomicに実行できるよ
>>795 D-RAM は、読んだらデータが壊れるから再書き込みするけど、
あれは読んだデータを後から書き込んでるから同時じゃない。
正解を教えてくれ
>>755 >>796 > という文章があったとします。
どこに? 君の脳内?
ちょっと頭冷やせよ。
そんなの基礎知識でしょ
文脈や前提を無視して言葉尻をとらえるのが大好きな方がいらっしゃるようで。
で、そういう人には揶揄や皮肉は通用しませんね。
746 名前:デフォルトの名無しさん:2006/08/03(木) 23:05:44 アセンブラまで降りる必要は必ずしも無いとは思うが メモリの読み込みと書き出しを同時(atomic)に行うことは (普通は)出来ないということくらいは知っておく必要がある。
>>787 排他だけなら、アセンブラとか、asm文とか使えばいいけど、
CPUを離すのは、API使わないと無理。
# というか使った方がいい。
# ユーザランドだけで実装されたマルチスレッドライブラリもあるけどさ。
破壊読み出しなのは、コアメモリもそう
>>803 もちろん、プロセッサはそのための命令を(普通は)用意しているが
コストがかかるため、普通にソースを書いた場合
コンパイラはその命令を使ったコードは出力しない。
( ゚д゚)ポカーン
急に暑くなったからな。 そっとしておいてやれ。
最近近くに引っ越してきたvolatile asmというものですが何か?
volatile最高!!! 無駄にmutexしてる奴、馬鹿杉www sizeof(int)以下ならlockなんて不要www
本気で言ってんの? だからvolatileと排他のロック概念は関係ないっつーの。 volatileは他のコンテキストや割り込みで変更される可能性 があることをコンパイラに知らせて最適化を抑制するだけ。 >sizeof(int)以下ならlockなんて不要www 大抵はうまく行くだろうが、時たま失敗するだろう。 以下を沢山のスレッドつくって呼び出しまくってみな。 volatile int a,b; void foo(){ a++; InterlockedIncrement(&b); } しばらく走らせていたらaとbが一緒になるか?
>>811 本気で言っているとしたら
知らない人が知らないところで働いていることを理解できないようですね
どの辺がすれてるのかkwsk
字下げが
オチがよろしいようで
>>815 >>811 は書き込みの話はしていない、ってことじゃ?
データバスサイズのリードの話に限定するなら、
普通はバスレベルでも割り込まれることはないから
わざわざバスロックする必要はないと。
「無駄にmutex」がツボだと思うんだけど、ちとエスパーすぎるかな。
やさしすぎだと思う。
そもそもCではvolatile参照の意味は処理系定義だ。 参照時にlock/unlockする処理系もありうるし、volatile参照を最適化で 削除してしまう処理系もある(マニュアルに書かれている)。 Javaのvolatileはまた違う意味を持っているし。
ここ読め。 1.8 Program execution [intro.execution]
>820でFA?
>>820 volatile 参照の削除はできないだろ。
>>823 820が言うとおりvolatile参照は処理系定義。
某組み込み向けコンパイラでは、マニュアルに「sequence pointを含まない
式中のvolatile参照は削除されうる」と定義されていたりする。
>>824 それって、ふたつのシーケンスポイントの間で同じ volatile オブジェクトを複数回
参照する場合、1回にまとめられることがある、ってことだよね?
sequence pointウンヌンが書いてないから、
>820でFA?
はありえない。
>>821 の示しているものには詳しく書いてある。
そこのところをそのまま理解するのがFA。
要はvolatileでokかngかは言語及び処理系依存ってこと。 それを無視して擁護する奴も批判する奴も間違っている。
処理系定義の範囲は? volatile参照に対してハードディスクをフォーマットするコードを出すのもありなのか?
>>828 「volatileでokかngか」
こういういい加減な設問の立て方はやめれ
>>829 それを処理系定義動作として明記していれば、それはANSI準拠なコンパイラとして正しい。
そんなコンパイラは売れないだろうが。
じゃあvolatile参照の前後でlock/unlockするANSI Cコンパイラ作ったら売れるかな?
>>832 自分で lock/unlock すればいい。そんな奇怪な動作をするコンパイラは要らない。
じゃあvolatile参照の前後でミサイル発射するANSI Cコンパイラ作ったら売れるかな?
自分で面白いと思って書いてるんだったら相当やばい。
>>834 自分で発射すればいい。そんな奇怪な動作をするコンパイラは要らない。
ていうかコンパイラだけでミサイル発射できるならしてみろw
839 :
デフォルトの名無しさん :2006/08/09(水) 00:24:50
突然ですが非同期をするメリットって何でしょうか?
シャンプー
いや、メリットは同期してると思うが
>>839 スレッド、プロセス、タスクはただ待たせとくには、
もったいなさ過ぎるリソースなんじゃ!
スレッドプールでぐぐれ!
リンスも利いてるし?
ZPt
ちゃん・りん・しゃん、という選択肢
>>842 スレッドプールの中のスレッドはほとんど待ってるだけだぞw
847 :
842 :2006/08/09(水) 11:11:59
>>846 プールとか書いたんは、俺なりの「サプライズ」や。
色んな意見があるのはわかっとるし、好きに言うたらええ。
俺はまた覚えたての言葉使って、レスしていくだけや。
んまあ、I/Oとか凍り付いて待ってる間に他の仕事が出来るのがメリットだわね。 多くの場合、他の仕事っていうのは、ユーザに対して「やってますよ、生きてますよ」っていう アピールをすることだったりするけどw
だっておまい、単純なスレッドプールなら、 例えばプールにスレッドが10個あってタスクが2個だったら8つは待ってるだけじゃんか。 まあ、忙しさに合わせてスレッド数を適当に増減させるような実装も可能だけど。
スレッドプールの利点 ・タスクが200個あるけど、同時に動くのは最大10個 ・スレッド生成が頻発な場合、生成のボトルネックを消す …
スレッド数の上限を制御したいときも使うわね ていうかすみませんでしたよ。 軽い気持ちで書いただけなんですよごめんなさい。
大したテクニックじゃない気がするんだが…。
大したテクニックじゃないといけないのか?
>>850 そんなの実装に依存。
議論するだけ無駄だなw
pool状態のthreadはqueueに入れないから、待つことはないって場合もあるだろうし。
>>855 スレッド、プロセス、タスクはただ待たせとくには、
もったいなさ過ぎるリソースなんじゃ!
スレッドプールでぐぐれ!
非同期のメリットは何かと聞かれてスレッドプールでググれって言われてもアレだな
858 :
デフォルトの名無しさん :2006/08/10(木) 00:56:12
このエディタは非同期でテキスト入力してるっていわれたんだけど じゃあ入力以外に何か処理やってるのかな?
個人情報の流出
仁義無きエディタ
キー入力拾うのと、バッファに突っ込むのが非同期なんじゃね?
>>858 GUIのエディタだと、
ウィンドウサイズ変えられるのに対応したり、
マウスで指定された範囲を反転表示したり。
しながら同時にテキスト入力できるのか!
865 :
デフォルトの名無しさん :2006/08/11(金) 22:57:19
どこまでがマジレスなのか…
866 :
デフォルトの名無しさん :2006/08/14(月) 21:40:21
みんなスレッドプールって最大数超えた場合どうしてる?
再起動
海に行く
オレは泳がないから
眺めてるだけでも心和むじゃまいか
潜りてー あの不要な音が聞こえない感覚が良いんじゃー
872 :
デフォルトの名無しさん :2006/08/18(金) 14:51:42
>>866 @IT:連載:.NETマルチスレッド・プログラミング入門 第4回
www.atmarkit.co.jp/fdotnet/mthread/mthread04/mthread04_01.html - 53k - キャッシュ - 関連ページ
スレッドプールのカスタマイズ
www.atmarkit.co.jp/bbs/phpBB/viewtopic.php?topic=27266&forum=12&3 - 26k - キャッシュ - 関連ページ
[ 他、www.atmarkit.co.jp内のページ ]
スレッドプール 最大数 の検索結果 約 1,440 件中 1 - 50 件目 (0.59 秒)
大阪には株式会社モータープールがあり、東京には株式会社月極がある。
MFCでマルチスレッドのプログラムを作成していますが、引数の受け渡しのところで悩んでいます struct ThreadParams{ int a; int b; int c; }; BOOL MyApplicationDlg::OnInitDialog() { … struct ThreadParams tParams; tParams.a = 1; tParams.b = 2; tParams.c = 3; AfxBeginThread(MyThread, (LPVOID)&tParams, THREAD_PRIORITY_NORMAL); return TRUE; } UINT MyApplicationDlg::MyThread(void * param) { struct ThreadParams tParams = (struct ThreadParams)(*param); ←ここで既に呼び出し元のtParamsが消えているかも? /* tParamsを使っていろいろ処理 */ return 0; } 上のようなコードを書いたのですが、OnInitDialog中のtParams変数のスコープは関数内だけなので MyThread関数でtParamsを受け取ろうとしたときには既に消えている可能性があるのではないかと思いました。 こういう場合には呼び出し元で new してスレッドの方で delete するとかで対処するのでしょうか? 他に何かよい方法があればアドバイスをお願いします。
MyThread()とダイアログクラスの結びつきが強いのなら、クラスメンバにしておけばいいんでない? 要は、スレッドよりも長寿命ならいいわけだから。 #ダイアログクラスよりもスレッドの方が長寿ならこの手は使えないのは当然だけど。
876 :
874 :2006/08/26(土) 10:20:36
そうですね。ぐぐって探してみましたがクラスメンバにしているサンプルがありました とりあえずこの方法でやってみます。ありがとうございました
>>874 あんたの心配は正しい。
領域を渡して後はスレッド側でよろしことする以外にも...
・スレッド側で (コピーしておくとして) そのパラメータを
使わなくなるまで親を待たせる。
・領域を静的に確保する。
・スレッドが起動してからパイプとかでパラメータをもらう。
等等。個人的には new / delete を使うことが多い。
volatileですべて解決します。 グローバル変数にvolatile属性を付けて置く。 これ最強。
何でvolatileネタって流行ってるの? とくに引っ張って面白いネタとも思えないけど
sizeof(int)以下ならvolatileでいいですよね? 排他は重いからやりたくないんですが・・・ という馬鹿が一時期沸いた
すごいな 全く意味のわからん質問だ
マルチスレッドなんか使わなければ解決
>>877 スレッドを越えてのnew / deleteは止めとけ。
つーか、調べると分かるが、状況によって手痛いしっぺ返しを喰らうぞ。
アホ発見
>>884 状況を具体的に説明してみろよ
>>884 それは874に宛てるべき内容だ。
呼ぶ側がdeleteするか、呼ばれた側がdeleteするかは統一するべきだとは思う。
呼ばれた側がdeleteする場合は、浅いコピーをして使い回す場合に対応できないからオススメできない。
>>886 > 呼ばれた側がdeleteする場合は、浅いコピーをして使い回す場合に
> 対応できないからオススメできない。
kwsk
シャローコピーで参照を共用してる場合 データレースが起きるよヤバイよって事じゃないの? そんなもん別スレッドに渡すなよと思うけど
889 :
888 :2006/08/28(月) 00:23:33
なんか違うな 忘れてくれ
しったかぶりっこ
参照ってもスレッドに渡す前に参照カウント1アゲるだろ
ぶるぶるぶりっこ
一体何の話をしてるのだろう?
ぶりっ子ロックンロール / 紅麗威甦
環境はWindowsです。 メインスレッドで生成されたWindowから、別スレッドを起動します。 このスレッドは、ファイルを1行づつ読み、 vector<string>に50件溜まったら、Windowへ通知します。 とりあえず下のような感じで組んだのですが、 Windowsが閉じられた場合、このスレッドを破棄しないといけません。 もしスレッドを破棄したらNetFileReaderのオブジェクトって、 解放されないのですよね。 こういうプログラムって、どうやって組むのが良いでしょう? static vector<string> text; void NetwordThread::execute(void* pData) { MyWindow* win = (MyWindow*)pData; NetFileReader* reader = new NetFileReader("hoge.txt"); string* line; while ((line = reader->readLine()) != NULL) { text.push_back(*line); if (text.size() > 50) { SendMessage(win->m_hWnd, WM_MY_MESSAGE, NULL, (LPARAM)&text); text.clear(); Sleep(10); } SendMessage(win->m_hWnd, WM_MY_MESSAGE, NULL, (LPARAM)&text); text.clear(); _endthread(); }
中断フラグを作って、メイン側で Window を閉じる時に フラグを On にする。 スレッド側は中断フラグを一行毎にチェックしてて、 On になったら、速やかに終了する。 通常のディスクファイル相手ならこれでいいと思う。 ネットワークファイルとかで一行の読み出しにすごく時 間がかかる場合があるならその読み出し処理自体を中断 する必要があると思う。
ていうか、「Windowが閉じられたら」とか「スレッドを破棄」とか書いてるけど 普通は、閉じるボタンが押されたら、フラグなりイベントなりでスレッドに対して終了を通知して ワーカースレッドは自分で後始末をしてから終了する、 GUIスレッドはワーカースレッドが終了するまで待機する っていうふうに作るのが普通だろ。
898 :
895 :2006/08/28(月) 21:54:13
どもです。 中断フラグをONするメソッド作って、中はMutexで排他処理、 スレッドのexecute()の方はSendMessage()をMutexで排他処理 しておけば、1行ごとにチェックまではしなくてよいかな? あと、スレッドの中でSleep()呼ばないと、このスレッドに完全に制御が移ってしまい、 スレッドが終了するまでWindowが固まってしまいます。 これはそういうもんでしょうか? マルチスレッドって、どこで処理が割り込むかわからないものだと思っていたのですが。
899 :
895 :2006/08/28(月) 21:55:29
>>897 書き込み中にレスが。
ええ、その「普通はこうだ」ってのが聞きたかったんです。
なにぶん素人なのもので・・・
固まらなねーよ。 プライオリティとかいじってなきゃな。
901 :
895 :2006/08/28(月) 22:25:55
_beginthread()呼んでるだけで、プライオリティはいじってないですね。 ActiveX内で、やってるからかなぁ。
>>895 >解放されないのですよね。
そもそも、なんで new で割り当ててんの?
>>898 > あと、スレッドの中でSleep()呼ばないと、このスレッドに完全に制御が移ってしまい、
> スレッドが終了するまでWindowが固まってしまいます。
SendMessage()のせいじゃね?
904 :
895 :2006/08/29(火) 14:19:52
>>903 その通りでした。SendMessageは使わない方がよさそうですね。
スレッドがデータ格納するバッファは、Window側でタイマーで定期的に監視。
スレッドがバッファに格納するときと、Windowがバッファから取得するときは、
mutexで排他処理かましておくと良いかな。
PostMessage()使ってみたら?
タイマーで監視しなくても、PostMessage()で合図送ればいんじゃね?
907 :
895 :2006/08/29(火) 21:41:10
PostMessageだと、ちょっと不安があってやめたんです。 たとえば、スレッドからPostMessageを呼んだ直後に、 Windowのスレッドがアクティブになって、Windowを閉じる処理をした場合、 Windowのハンドルが無効になった後に、メッセージを飛んできて、 死亡したりしませんかね?
誰が死亡するの?
909 :
895 :2006/08/29(火) 21:50:03
オサーンのプログラム。無効なウィンドウハンドルに投げようとして ハングしたりしないかなと。
,、‐ " ̄:::゙:丶、 ,r::::l3゙::::::::/ハヽ:ヽ::::、:ヽ {::://:::::::// ヽ\ト、:::::::! ヾ l:::::::/ 丶 `ヾ ィ、:::| |;:r::| O` 'O ゙ハ| < ないない ヽハ :.:. :.: レ ´\ r‐--‐、,ノ r、 r、/ヾ ̄下ヘ ヽヾ 三 |:l1、_ヽ/__ .ィヽ \>ヽ/ |` } n_n| | ヘ lノ `'ソ l゚ω゚| | /´ /  ̄|. | \. ィ ___ | | | ノ l | | | | i:| |
>>907 > メッセージを飛んできて、
> 死亡したりしませんかね?
メッセージを割り込みみたいなもんと勘違いしてないか?
912 :
895 :2006/08/29(火) 22:58:03
いや、それはないです。 PostMessageも当然、中でいろいろやってますよね。 PostMessageで実際にキューにメッセージ入れる直前に、 Windowのスレッドに切り替わることってないんですかね?
そろそろスレ違い
>>909 無効なハンドル次第では、デスクトップの再描画とか起こるかも。
>>914 909じゃないけど詳しく教えてください
そりゃロックしたままSendMessageしたらデッドロックだろうよ
917 :
デフォルトの名無しさん :2006/09/06(水) 21:28:12
居なくなった人のプログラムを押し付けられたんだけど、 CreateThread()した後、即CloseHandle()している。 どうして即CloseHandle()するのか、 Thread関数内のExitThread()直前に呼べばいいんじゃないのか、 そもそもCloseHandle()しなくてもExitThread()するんだから要らないんじゃないのか と思うんですが、誰も(??) そのままにしておけばいいんでしょうか。
>>917 MSDN の CreateThread あたりに理由は書いてあると思ったけど、
調べてみた? 推測はほどほどにして、ちゃんと確認したほうがいいよ。
>>917 > Thread関数内のExitThread()直前に呼べばいいんじゃないのか、
ハンドルの話じゃないけど…
マルチスレッドプログラミングにおいて、「〜の直前だから大丈夫」
なんてこと考えてたらはまるよ。
>>917 CreateThread - ExitThread - CloseHandleするのがここでのならわし。
盲目的にこうしてればいいよ。
ぉぃぉぃ
いやmmapしないとダメ
923 :
デフォルトの名無しさん :2006/09/08(金) 12:38:24
ロックしないでグローバル変数に(intなど機械語1命令で読み書き可能な サイズという条件で)アクセスするケースを考えます。 int a; void thread1(){ while(1)a=0x0000ffff; } void thread2(){ while(1)a=0xffff0000; } void thread3(){ while(1)printf("%08x\n",a); } このとき、thread3で0x0000ffffか0xffff0000以外の数字が 表示される可能性はありますか?
924 :
923 :2006/09/08(金) 12:40:49
補足ですが、シングルプロセッサとマルチプロセッサ両方の ケースでどうなのか知りたいです。環境はWindows2000以降の x86アーキテクチャを想定しています。
aの初期値が延々と表示される可能性すらあるな
volatile厨臭いな 釣りか? 釣られたのか?
>>923 メモリーバスが CPU のバストランザクションをソフトの都合に会わせて
実行する保証はどこにもないんだから
バスサイズ 8 bit のシステムで
1 on cpu0
2 on cpu1
3 on cpu2
ってシチュエーション考えれば何でもありじゃん
あっそう
929 :
923 :2006/09/09(土) 02:25:04
>>925 >>926 すみません。初期値の部分は、
volatile int a = 0xffff0000;
とさせてください。後付申し訳ないです。この辺はあまり捻らないで(^^;)
>>927 >ってシチュエーション考えれば何でもありじゃん
実際問題として、Windowsのマルチプロセッサ環境で失敗する
例を容易に確認できますでしょうか? ハード環境を簡単に
用意するわけにも行かないので、いろんな人が見ているここに
尋ねてみました。
シングルプロセッサでは失敗するケースはこれまでの経験上無い
ものと思われますが…(こちらは失敗するケースを見たことないです)
前スレでまったく同じ議論があったよ 保証されるかどうかはアーキテクチャに強く依存する それこそIntelとAMD、Intel内でもその世代により異なる >シングルプロセッサ マルチコア時代にそういう括りはやめたがいい HTもキャッシュ絡みでerattaがあった ひとつ聞いとこう、趣味?仕事?
386SX以外の32bitx86は メモリバス(システムバスでもHTバスでも)は32bit同時に読み書きするだろ。 キャッシュが反映されないとか関係ない。 全部(全bit)書き込まれるか、全部書き込まれないかどちらか。
あ、ちゃんとアラインされている場合の話ね。
>931-932 マルチプロセッサ環境で、あるCPUが内部キャッシュ内に保持しているDWORD 値の一部バイトを書き換えて、ライトバックする前に、ほかのCPUがDWORDの 一部バイトを書き換えるという状態になったらどう動作すんの?
934 :
923 :2006/09/09(土) 09:07:35
>>932 Interlock系のAPIがマルチプロセッサ環境では32bitアラインを要求しますね。
関連があるのでしょうかね?
>>933 こちらへのレスではありませんが、おっしゃるケース
(一部書き換え)は考えてません。問題にしたいのは
全ビット書き換えた時読み出し時に一部しか書き変わ
っていない状況があるかどうか、なので。
ちょっと動作検証と、ロック有り無しの場合で性能的に
どれほど差が出るのかプログラムを作って試してみたいと思います。
935 :
デフォルトの名無しさん :2006/09/09(土) 09:21:18
volatile最強!!!
Interlockとか_MemoryBarrier使わない必要性あるの? 速度が必要ならアルゴリズムとか排他制御の範囲とか無待機アルゴリズムとか から高速化できないの? スレッドの優先順位とか、他のプロセスの稼動状況とかでも状況変わるから 動作検証を完全にやることは無理でしょ。 CPUやMBの仕様書をNDA結んで手に入れて調べるぐらいしないと。
>>933 それは「起こらない」でしょ。
なぜならば、キャッシュ間のコヒーレンシを保つための仕組みを持っているのが
マルチプロセッサシステムだから。
>>934 特定少数の chip setに限定するとかなら話は別だろうけど,
C コンパイラが LOCK prefix つけて load/store するコードを
吐き出すわけではないし, ハードウェアの作り次第だと思われ...
>>937 の仕組みが外部バス接続のために遅くなり、糞CPUと呼ばれたのがPenD。
940 :
デフォルトの名無しさん :2006/09/09(土) 10:30:49
ついにvolatileの最強さが証明されるわけだ
>>811 おめでとう
>>937 何が「起こらない」っと言ってるのか...。
942 :
923 :2006/09/09(土) 12:45:41
>>936 >>938 ロックしないと明らかにまずい状況はもちろんロックしますが、
単純な場合はロック無しでできたらいいという場面もありそうです。
皆さん、スレッド間で共有されるグローバル変数全て、万一の場合に
備えてくまなくロック系API使ってアクセスしてますか?
「書いて」「読んで」その状況において不都合がない場合は、
API通さずに普通のCの文法で書ければ言うことはないじゃないですか。
スレッド系の解説してる本にも、単純なカウンターとかロック系の
API無しでアクセスしてます。ここで問題にしているのはそういう
ごく単純なプリミティブなアクセスの話です。
NDAや「ハードウェアの作り次第」とか、そういう話まで持ち出されるのは
個人や小さい事業所でどうこうするのは不可能ですし、現実的なアクション
とは到底言えないと思います。
要は世に出回っている大抵のWindowsマシンでおかしくならない線を
探せばいいのだと思います。パッケージには全てのマシンで動作保障
するものではありませんとか書いてるソフトもありますし、試せる
範囲でおかしくならなければ(試して失敗が一つも無ければ)、
完全な厳密性までは得られなくても、こちらのスタンスとしてはOKです。
943 :
923 :2006/09/09(土) 12:46:30
厳密性を完璧にするなら世の中のマシン全部で試さないといけない じゃないという話にもなりますし、それはやはり現実味の無い話と しては上に書いてあることと大差ありません。理論にも実装にも ミスが無くてもおかしくなる環境は必ずあります。 一応持ってるマシンで検証プログラムを走らせましたがエラーする ケースは一度も起きませんでした。 性能に関しては、ロック無しを1とした場合、Interlocked系で読み書き すると5倍、CriticalSectionで排他すると200倍近い速度低下が起きます。 (テストプログラムは極端な例でしょう) 実際の使用状況は置いておき、5倍の負荷は精神的に嫌な感じです。 この辺気にしない人もいるでしょうが、気にしない人は他の場合でも 気にしないでしょうし、積み重なるともっさりしたソフトが出来そう なので、検証不可能な厳密性よりもこういうほうに労力や気を払いた いですね。 一応ソース貼っときますので、もし失敗例が実際に観測された人が居たら 教えてください。Windowsシステム上で一つでも反例があれば納得せざる を得ません。逆にある程度のサンプルで試して一度もエラーが無ければ それはOKというのが世の中というものでしょう。
944 :
923 :2006/09/09(土) 12:50:44
#include "stdafx.h" #include "windows.h" #include "winbase.h" #include "process.h" #include "mmsystem.h" #pragma comment(lib, "winmm.lib") #if 1 //ロック無し #define set_a(n) a = n #define get_a(v) v = a #elif 0 //Interlocked系で読み書き #define set_a(n) InterlockedExchange((long*)&a,n) #define get_a(v) v = InterlockedExchangeAdd((long*)&a,0) #else //CRITICAL_SECTION排他 #define _CS CRITICAL_SECTION cs; #define set_a(n) {EnterCriticalSection(&cs); a=n; LeaveCriticalSection(&cs);} #define get_a(v) {EnterCriticalSection(&cs); v=a; LeaveCriticalSection(&cs);} #endif 続く
945 :
923 :2006/09/09(土) 12:51:29
volatile int a = 0x00001111; volatile int t1_ct,t2_ct; void __cdecl thread1(void *param){ while(1){ set_a(0x00001111); t1_ct++; } } void __cdecl thread2(void *param){ while(1){ set_a(0x22220000); t2_ct++; } } 続く
946 :
923 :2006/09/09(土) 12:52:50
int main(int argc, char* argv[]) { #ifdef _CS InitializeCriticalSection(&cs); #endif unsigned int id1; HANDLE h1 = (HANDLE)_beginthread(thread1, 0, &id1); unsigned int id2; HANDLE h2 = (HANDLE)_beginthread(thread2, 0, &id2); #if 0 while(1)printf("%08x\n",a); #else printf("実行中……\n"); int loop = 0; int false_ct = 0; DWORD time = timeGetTime(); while(loop++ < 100000000){ int t; get_a(t); if(t != 0x00001111 && t != 0x22220000) printf("不整合発見(%d):%08x\n",++false_ct,t); if((loop & 0x7fffff) == 0) printf("loop:%d……\n",loop); } 続く
947 :
923 :2006/09/09(土) 12:53:28
time = timeGetTime() - time; TerminateThread(h1,0); TerminateThread(h2,0); printf("ループ%d回、失敗%d回、実行時間%.3f秒\n",loop-1,false_ct,(double)time / 1000); printf("スレッド1実行回数%d回\n",t1_ct); printf("スレッド2実行回数%d回\n",t2_ct); #ifdef _CS DeleteCriticalSection(&cs); #endif #endif return 0; }
どうせなら、レスの最後を /* 続く として、次のレスの頭を >xxxから */ とでもしてくれたらコピペの(後処理の)手間が減るのだが。
949 :
923 :2006/09/09(土) 12:58:46
済みません。あと、TerminateThreadしてるのはご愛嬌ということで。
>>943 > 一応持ってるマシンで検証プログラムを走らせましたがエラーする
> ケースは一度も起きませんでした。
じゃ、あなた的には、それでいいんじゃないでしょうか?
> 実際の使用状況は置いておき、5倍の負荷は精神的に嫌な感じです。
> この辺気にしない人もいるでしょうが、気にしない人は他の場合でも
> 気にしないでしょうし、積み重なるともっさりしたソフトが出来そう
> なので、検証不可能な厳密性よりもこういうほうに労力や気を払いた
> いですね。
「いかにして、ロックするべき部分を局所化して、ロックコンディションの
テストする回数を減らすか」
を考えるべきであって、
「ここで動くんだから大丈夫じゃないか、きっとよそでも動く!」
ってな発想はしてはならないと思いますけど。
じっさいに、4CPU程度のマシンで動いていたけど、16CPU程度の NUMA
アーキテクチャのターゲットマシンの持っていった場合、動作しなかった
って前例は何度もみてます。
951 :
923 :2006/09/09(土) 13:50:37
>>950 ソースを出してるので、失敗した出力を貼って
いただけないでしょうか? 動作させた環境も
出来たらお願いします。
もちろん、手持ちのマシンで動けば問題ないし、 たまにクラッシュしてもビジネス上問題ないならそれでいいんじゃ? 950も言ってるが、スレッドで共有する情報の塊に対してロックをかけるべきであって、 1足すとか状態を読んでそれに対する処理を行いさらに書くことはできないと思っておいたほうがいい。 それとソースだが、何でintrinsic命令使わないの?関数呼び出しコスト余計にかかってるよ。 printfのコストが多すぎだと思うが、計測間違ってない? あと、そこまで考えるならtimeGetTimeはつかえないでしょ。 精度の設定もしてないし、明らかに少しかじった初心者がやりそうなソースだ。
だからホビーなんじゃないの?と
954 :
923 :2006/09/09(土) 14:05:31
>>952 >1足すとか状態を読んでそれに対する処理を行いさらに書くことはできないと思っておいたほうがいい。
もちろんです。
>printfのコストが多すぎだと思うが
?
全て成功するケースでは、1億回のうちprintfは11回だけです。
無視しても問題ないと思いますが。
(途中経過のprintfが無しでも、ストップウオッチ計測で
十分優位な差が得られるほど負荷が変化するのはわかりますし、
なんなら途中経過のprintfは取ってください)
計測ループの中ではロック系のAPI以外の呼び出しは上記の
途中経過表示の微々たるprintf以外無いですよ。
>timeGetTimeはつかえないでしょ。
動作が秒単位に対してtimeGetTimeは10msオーダーです。
精度としては十分じゃないのですか? もし不足だと感じたら、
パフォーマンスカウンターでも使って書きなおしてください。
955 :
923 :2006/09/09(土) 14:07:51
補足、 >十分優位な差が得られるほど負荷が変化する ロックするしないを切り替えたときの負荷の変化です。
956 :
923 :2006/09/09(土) 14:13:30
後、今回の趣旨は、読み出し失敗があるかどうかなので、 そちらに関してお話ください。 レスを見ていると相当な環境の方もいるようですし、 ロック無しでの書き込みや読み出しがそれほど使用に 耐えないほどの不具合があるものなら、簡単に失敗の ケースが出ると思います。 失敗した状況が貼られれば何より説得力がありますので、 よろしくお願い致します。
957 :
923 :2006/09/09(土) 14:15:05
あと、失敗しない限り発言しないでください。 失敗しなければ問題ありませんので。
>>942 > 要は世に出回っている大抵のWindowsマシンでおかしくならない線を
> 探せばいいのだと思います。
最近の風潮か?
製品事故が多くなった理由が垣間見えるようだ...。
>>943 > 理論にも実装にもミスが無くてもおかしくなる環境は必ずあります。
技術屋として見過ごせないんだけど、「ある」と言い切れる理由は?
>>957 > あと、失敗しない限り発言しないでください。
ここは、お前の検証スレじゃない。
そういう発言したいなら、自前の掲示板でも作れ。
intrinsicはスルーか。ソースまともに読むわけ無いだろ金ももらってないのに。 失敗する環境探したいなら、自分でマシン買ってやってろ。
960 :
923 :2006/09/09(土) 14:27:21
>>958 >製品事故が多くなった理由が垣間見えるようだ...。
どうもすみません(^^;)
>技術屋として見過ごせないんだけど、「ある」と言い切れる理由は?
話がそれたかもしれません。済みません。ユーザー環境の
不具合などです。完全な検証が出来ない以上、分る範囲で
調べることしか出来ないと思うので、完全完全を言われると
身動き取れなくなってしまうといいたかったのです。
後、
>>957 は悪戯じゃないですか?
>>960 > ユーザー環境の不具合などです。
そのユーザー環境に「理論か実装」の不具合があるんでしょ。
「全ての環境で試験なんかやってられねー」と言うのは当然至極なんだけど、
理論的な裏づけもなく1万回やったから大丈夫と言うのはちょっと違う気が
する。
もちろん現実的には取りきれないバグをタイミングとかで逃げて1万回テス
トしたから多分大丈夫だよねーと言って出すケースはないわけじゃないけど、
技術屋としてはもやもやが残ってる。
そもそもこの話は「検証不可能な厳密性」じゃないよ。いくつもの論文があ
るし、このスレでも議論されてる。 (まともな意見のみを取り出すのは難しい
が)
> 後、
>>957 は悪戯じゃないですか?
いたずらなら、2行目は
>>957 へのレスだ。
でも、いたずらかどうかにかかわらず1行目はあんたへのレスだよ。
>>923 提示されたソース読んでないけどさ、
同じ環境で何度ループしようがあまり意味ないんじゃね?
ゲーム開発では、3日3晩デモループさせて検証することだってあるんだよ?
それくらいのレアケースだって見逃せないっていうのは
技術者の自己満足じゃなくて、正しい姿勢なんじゃないか?
少なくとも「オレのマシンで動いてるからOKでしょ」って言う人とは
一緒に仕事したくないね。
964 :
923 :2006/09/09(土) 17:02:17
うざいとか言われつつ書き込んで済みません。
>>963 >同じ環境で何度ループしようがあまり意味ないんじゃね?
集中的に問題が起きるようなサンプルになってるとは思いますが。
たとえば似たようなケースで、あのサンプルの変数を代入じゃなくて
a++ とかにすれば値が順次増加せずに書き戻されたりするケースは
すぐに出ますので、検証手法としてあながち外れてるとも思えないです。
話はそれますがゲームの検証に関しては良く存じてます。
リリース前は2週間電源入れっぱなしで落ちないかどうか
とかやりますよね。(昔の話です)
>オレのマシンで動いてるからOKでしょ
オレのマシンだけというより、動かせる限りにおいてエラーに
ならなければ、というふうに考えてます。それ以上はやりよう
が無いですし。
こちらも手持ちの環境で複数台のマシンでチェックしても
エラーになるケースは無いので、もし他の方でエラーが実際
出るなら教えてもらえるとありがたいなと思ったしだいです。
965 :
923 :2006/09/09(土) 17:20:22
>>962 >このスレでも議論されてる
結論はどうだったのでしょう? 以下、各行が別スレッドで動くとして、
a=0x00001111;
a=0x22220000;
b=a;
で、bが0x22221111になるケースがあったのでしょうか?あまり対象を
広げても大変ですし、身近なWindows環境で。
たとえば68000CPUとかでアライメントを知らない人が、奇数アドレスに
byteより大きな単位でアクセスして落ちたりすると面食らうじゃ
ないですか。
PC互換機上で0x22221111のケースって、アライメント違反ほどに顕著な
現象じゃないですよね? で、実際のアプリでも、検証プログラムでも
不具合を(少なくとも当方は)見たことが無いとなると、Windowsアプリでは
「汎用レジスタから奇数アドレスへのアクセスが(遅いけど)許可されて」
いるように0x22221111のようなことは起こりえないものとしてプログラムを書いて
もいいんじゃないかと思ったのです。Windows依存だといわれればその通りです。
PC互換機の設計図やWindowsアプリの構築方法にやったらイカン
と明示してあれば従うのにやぶさかじゃないですけどそういうソースって
このスレで議論されたという中で、もし出てきたのならお教えください。
もしくは、現象が簡単に再現するプログラムの書き方があれば反例
として文句をつける余地はありません。
>理論的な裏づけもなく
もし検証プログラムに理論的なミスがあれば指摘してください。
>>923 >int a;
>void thread1(){
> while(1)a=0x0000ffff;
>}
>void thread2(){
> while(1)a=0xffff0000;
>}
>void thread3(){
> while(1)printf("%08x\n",a);
>}
>
>このとき、thread3で0x0000ffffか0xffff0000以外の数字が
>表示される可能性はありますか?
概出だと思いますが
CPU/ハードウェア(メモリの実装方法とか)/OSによって違うでしょう。
それ以上でもそれ以下でもありません。
967 :
923 :2006/09/09(土) 17:29:41
>>959 >intrinsicはスルーか。
済みません、仰りたいことの意味が良く分りませんでした。
このプログラムの要点は、
volatile long a = 0x00001111;
void thread1(){
while(1)a=0x00001111;
}
void thread2(){
while(1)a=0x22220000;
}
void main(){
_beginthread(thread1);
_beginthread(thread2);
while(1)if(a != 0x00001111 && a != 0x22220000)エラー;
}
です。組み込み命令云々の余地があるのでしょうか?
968 :
923 :2006/09/09(土) 17:41:20
>>966 >CPU/ハードウェア(メモリの実装方法とか)/OSによって違うでしょう。
どうも。
Windowsでどうなのかが知りたいのです。
こちらとしてはWindowsアプリで問題ないという裏が取れればOKです。
このマザーボードだと駄目だ、とか言うのがあれば使えないですよね。
>>965 > 結論はどうだったのでしょう?
自分で読もうと言う気はないのか?
> もしくは、現象が簡単に再現するプログラムの書き方があれば反例
> として文句をつける余地はありません。
そんなもんがあったら苦労はしない。
> もし検証プログラムに理論的なミスがあれば指摘してください。
検証プログラムで現象が出ないからと言ってプログラムが正しいと考える
お前の思考。
>>923 とりあえず4CPUのマシンでも異常なしで動きましたのでご報告します。
>>969 >検証プログラムで現象が出ないからと言ってプログラムが正しいと考える
>>923 さんはそんなこと言ってないと思いますよ。
少なくとも検証プログラムですぐに問題が出るなら使い物にならない
と考えてるだけでは?
972 :
923 :2006/09/09(土) 18:57:46
>>970 ありがとうございます。
こちらは1億回を10億回にしても問題出ませんでした。
Pen4の1CPU-HT環境と、Pen3の1CPUです。
ちなみに、類似のプログラムとしてaに加算するケースを
動作させてしっかりエラーになりました。マルチスレッド
でのコンテキスト切り替えとアクセスを検証するプログラム
として動作がある程度的を得ているからだと思います。
また、加算だとPen3ではぜんぜんエラーにならないのも面白いですね。
1CPUなのである程度予想してましたが、コンテキスト切り替えの状況
がHTと違うようです。
>>971 擁護どうもです。970の人?
↓ちなみに加算テストへの変更点ですが、
* + 巛 ヽ 〒 ! + 。 + 。 * 。 + 。 | | * + / / イヤッッホォォォオオォオウ! ∧_∧ / / (´∀` / / + 。 + 。 * 。 ,- f / ュヘ | * + 。 + 。 + 〈_} ) | / ! + 。 + + * ./ ,ヘ | ガタン ||| j / | | ||| ――――――――――――
974 :
923 :2006/09/09(土) 18:59:57
#elif 1 //インクリメントテスト #define _INC #define set_a(n) a++ #define get_a(v) v = a int max = 0; //これはmain内のローカル変数でも良い #elif 0 //Interlockedでインクリメントテスト #define _INC #define set_a(n) InterlockedExchangeAdd((long*)&a,1) #define get_a(v) v = InterlockedExchangeAdd((long*)&a,0) int max = 0; : : と、以下がループ内抜粋 int t; get_a(t); #ifndef _INC if(t != 0x00001111 && t != 0x22220000) printf("不整合発見(%d):%08x\n",++false_ct,t); #else if(max < t){ max = t; } if(max > t){ printf("不整合発見(%d)%d,max:%d\n",++false_ct,t,max); } #endif です。HTマシンではInterlockedしないと一瞬でエラー続発です。
お前用の検証スレじゃないんだけど。 もう言いたいことは言ったろ うざいからwikiでも立ててそっちでやってくんね?
どうしても書き込みたいならコテハンかトリップたのむ。
>>976 みたいな馬鹿はおいといて
2chの住民に検証協力してくれというなら
>>975 くらいの準備はしても良いと思う
結果報告なんかをここでやらないならいいよ 正直つまんないのでウンザリしてる
>978 >975 は遠回しに断ってるんじゃないかな。
>>943 根本的なところが馬鹿っぽいのに、
とても流暢に(内容的に脱力な)文章を書ける才能に感嘆する。
>>975 どうせならワームとして世界中のPCにばら撒いて
宿主PC上の実行結果を自分宛てにレポートさせるように
実行させれば良いのでは?
前々スレくらいでvolatile厨を繁殖させた者です。 この話題って、あの時のフラグ変化の検出の話題と凄く似ていると思う。 あの時は単なるフラグで、1ビットでも変化している事を検出できれば 良かったから、不必要にややこしくしそうで触れなかったんだけど。 前の時のポイントは、 1. メモリから読み込んだ値を利用(計算)した結果を書き込むのではなく、 完全に新規な値をメモリに書き込む。 2. 更新前の古い値を他のプロセッサがキャッシュの関係で読み込んでも、 伝搬されて更新された値を近いうちに読み込めればよい。 という前提において、 必ずしも同期を取らなくても動作に支障はないが、最適化による レジスタへの張り付きを防止するためにvolatileは必要となる。 今回も似たようなもので、更新前のメモリの内容に依存しないので、 ワード境界に整列されたワード単位のメモリ転送命令がアトミックに 行われるかどうかを確認するだけで解決できるんじゃないの?
984 :
983 :2006/09/09(土) 22:57:37
ついでに、OS依存、アーキテクチャ依存だって言う必要もないのでは? C言語から見たら、スレッドの存在そのものが環境依存なわけだし。 >IA-32 Intel® Architecture Software Developer's Manual, >Volume 3A: System Programming Guide >7.1.1 Guaranteed Atomic Operations これを見ると、 >basic memory operations will always be carried out atomically なわけで、少なくともワード境界に整列されたワード転送なら アトミックに行われる事が保証されているように読めるのだが。
次スレ立ってる?
立てるわ
>>983 > という前提において、
そういう前提かどうかは明らかにされていない
>>984 > ついでに、OS依存、アーキテクチャ依存だって言う必要もないのでは?
「世に出回っている大抵のWindowsマシンでおかしくならない線」
というあいまいな線引きしかなされていない
つーかさ、
spec等から確認できることもせずに、いきなり検証コード持ち出して
「ホラ、動いてるから問題ないじゃん」
なんて言われてもさ、そのコード・やり方を信用する人っているのかね。
仮に確認できても、前提を考えれば、いかに狭い範囲でしか使えないかが
すぐに分かると思うんだが、それをしない理由はなんだろうね。
もう少しアタマ使えないかな。
>>988 >spec等から確認できることもせずに、いきなり検証コード持ち出して
>「ホラ、動いてるから問題ないじゃん」
>なんて言われてもさ、そのコード・やり方を信用する人っているのかね。
悲しいけど現実にはかなり沢山いると思う
実際事故は多発してるでしょ?
990 :
983 :2006/09/10(日) 01:08:03
>>988 >「世に出回っている大抵のWindowsマシンでおかしくならない線」
>というあいまいな線引きしかなされていない
これが微妙な線引きだと言いたいのもわかるけど、
世の中のPC〜WSクラスでSMP/Multi Coreが可能なCPUの
大半はIA-32なアーキテクチャなんじゃないの?
>そういう前提かどうかは明らかにされていない
まず、
>>923 のコードではaから読み出した結果を利用して
aに再代入しているわけではないので、1.の前提は成り立つ。
で、「0x0000ffffか0xffff0000以外の数字が表示されるか」から、
aの更新が他のプロセッサに即時に伝搬される必要もないし、
どちらかの値になれば良くて、読み出し結果が0xffffffffの
ように混ざり合わなければいいだけなので、2.も成り立つ。
#とりあえず、初期値が延々表示される、、ってのは置いといて…。
少なくとも、今のところはこの考え方がまずい、
って証拠も誰も示していないんだよね。
991 :
983 :2006/09/10(日) 01:23:24
この辺のところはDCLみたいに覆されることもあるかもしれない。 で、DCLにも気になっているところがあって、 Singletonを保証するためのDCLは危険なのは解るんだけど、 100%のSingletonであることに依存しているわけではなくて、 運悪く初期化時に複数インスタンスが生成されてしまっても 許容できる状況でもDCLは使っちゃいけないのかな? 生成にそれなりに時間かかるからキャッシュ目的でSingletonに してるけど、複数回生成されて違うオブジェクトを返そうが、 単なるキャッシュだから実害はないっていうような場合とかで。
マルチスレッドを扱い続けて30年の漏れが断言するが、
>>923 のコードでは絶対に「0x0000ffff か 0xffff0000 以外の数字」は表示されない!
これで勘弁してもらえないか?
CPUによる
俺なんかマルチスレッドと暮らし始めて60年だぜ
うめようよ
2chを見続けて10年の俺が断言するが、
>>992 の言うことに間違いはない!
>>988 >なんて言われてもさ、そのコード・やり方を信用する人っているのかね。
顔が見えないのをいいことに、著しく礼儀を欠いた発言をする人間も信用できないが
ヒント:2ch
>>997 いるよ。
うちの新人はWebで調べたコードは絶対間違いないって言い張る。
そういえば、去年までいた中国人も同じ事いってたよ。
1001 :
1001 :
Over 1000 Thread このスレッドは1000を超えました。 もう書けないので、新しいスレッドを立ててくださいです。。。