- 1 名前:デフォルトの名無しさん mailto:sage [2006/09/10(日) 00:13:53 ]
- マルチスレッドプログラミングについて語るスレ。
OS・言語・環境は問わないが、それゆえ明記すべし。 その1 pc3.2ch.net/tech/kako/997/997345868.html その2 pc5.2ch.net/test/read.cgi/tech/1037636153/ その3 pc8.2ch.net/test/read.cgi/tech/1098268137/ その4 pc8.2ch.net/test/read.cgi/tech/1130984585/
- 271 名前:デフォルトの名無しさん mailto:sage [2007/03/04(日) 08:20:53 ]
- >>268
>>261はいろいろ省略してるのだけど、InterlockedCompareExchangePointerを使えといってるのだと思うよ。 >Cで書いた場合のコードに、>>255と本質的な違いがあるのか?と >問いたかっただけです。 どちらも遅延初期化で本質的な違いはなさそうだけど、 >>261はダブルチェックロッキングが正しく出来ているが>>255には穴がある。
- 272 名前:259 mailto:sage [2007/03/04(日) 08:27:12 ]
- >>269
理解しましたm(_ _)m 他スレッドのInterlockedExchangePointer()によって値が変えられていたら deleteするという意味なのですね。 Cで書くと static CRITICAL_SECTION *p = 0; if (!p) { CRITICAL_SECTION *q = malloc(CRITICAL_SECTION); InitializeCriticalSection(q); InterlockedExchangePointer(&p, q); if (p != q) free(q); } でしょうか。
- 273 名前:259 mailto:sage [2007/03/04(日) 08:30:03 ]
- んが。
malloc(sizeof(CRITICAL_SECTION)); ですね。 それと。InterlockedExchangePointer()ではなく、 InterlockedCompareExchangePointer()を使わなければならないのですか。 むずかしい...。
- 274 名前:259 mailto:sage [2007/03/04(日) 08:32:30 ]
- >>271
>>255のコードの穴というのは、>>259に書いたのとは別のものでしょうか。
- 275 名前:デフォルトの名無しさん mailto:sage [2007/03/04(日) 09:21:12 ]
- あーそうか、ほんとごめん。
確かに>>271の通り、CompareExchangeの方のこと(つまり>>258が俺の凡ミス)。 俺が重要な部分を間違えていたのに、意図を理解してくれる人がいてくれて助かった。 他の人も含め、ごめんね。 >>259では、本質的な解決にならないと思うよ。 つまり、比較(テスト)と初期化(&代入)の間に他のスレッドに割り込まれる可能性を消すには atomicなCASを実行するしかないって事。
- 276 名前:デフォルトの名無しさん mailto:sage [2007/03/04(日) 09:31:57 ]
- あ、そうか、>>255を見るとInterlockedを使っているのか。
でも、InterlockedIncrementは正負と0しか判定できないんじゃなかったかな。 で、仮に 初期値を-1として 2^32個以上のスレッドが同時に初期化部に入ることは有りえないとして >>259の修正(Inc失敗なら他のスレッドを待つ)を加えて 当然volatileにして とすれば、正常に動くのかな。 でもそこまでするなら、やっぱりCASを使う方がまともかと。
- 277 名前:259 mailto:sage [2007/03/04(日) 09:40:12 ]
- >>276
はい。CAS方式がエレガントでまともなコードであると納得できました。 Sleep()ループで待つなんてカッコ悪いことは出来ればしたくありません...。 有難うございます。
- 278 名前:デフォルトの名無しさん mailto:sage [2007/03/04(日) 09:45:22 ]
- ここまでやれば大丈夫だと思うけど。
if (!initialized) if(InterlockedIncrement(&lock) == 1) { pthread_mutex_init(&mutex, 0); initialized = 1; メモリバリア〜〜 } else { while (!initialized) { Sleep(1); メモリバリア〜〜 またはinitializedが揮発性であることが必要 } } } 老婆心から言えばスレッド生成前までに作っておいたほうがよいと思う。 スレッド生成後の初期化なんてバグの元。 PTHREAD_MUTEX_INITIALIZERマクロが何をやってるか調べてみたら何かヒントがあるかもしれないね。 javaで有名になったダブルチェックロッキングの話はまだ半分くらいしか理解できてないしなorz
- 279 名前:デフォルトの名無しさん mailto:sage [2007/03/04(日) 09:47:50 ]
- InterlockedIncrementはWin95以前だと正負と0の判定しかできないので>>255のようには使えないよね。
あと厳密に言えばの話だけど このスレの上のvolatile関連の議論からするとinitialized=1;の変更がキャッシュのせいで 他のスレッドに伝わらないかもしれない(規格的には)ので>>255のinitializedにはlock命令が必要だけど lock命令を追加しようとすると結局>>261みたいになってしまうんじゃないかな。 別に言わなくてもわかるだろうけど >>255は volatile static int lock = 0; >>272は volatile static CRITICAL_SECTION *p = NULL; if (p != q) { DeleteCriticalSection(q); free(q); }
- 280 名前:デフォルトの名無しさん mailto:sage [2007/03/04(日) 09:49:12 ]
- > PTHREAD_MUTEX_INITIALIZERマクロが何をやってるか
これはさすがに定数値を{}なりで囲んでるだけだと思うけど。 Cでも使えるんだし。
- 281 名前:259 mailto:sage [2007/03/04(日) 09:52:14 ]
- PTHREAD_MUTEX_INITIALIZERは単に{ 0 }
とかだと思います。 >>279 うわ。赤面しまくりです...。 ぶっちゃけUnixベースのライブラリをちょろっといじくってWin32に 移植しようと思っただけなのですが、こんなワナが待っていたとは 思ってもいませんでした。
- 282 名前:デフォルトの名無しさん [2007/03/04(日) 10:24:41 ]
- 下の例の場合変数iにvolatileは必要かどうか質問です。
lock, unlockがメモリバリアだから必要ないという認識なのですがつけている例も見ます。 >>261だとlockせずに読んでる箇所もあるので必要なのかもしれませんが、 この辺の基準ってどうされていますか? int i; thread_function() { mutex.lock() i = i + 1; mutex.unlock() }
- 283 名前:デフォルトの名無しさん mailto:sage [2007/03/04(日) 10:32:03 ]
- だれか
.NET Frameworkのメモリモデルとかに詳しい人おらんかね?
- 284 名前:デフォルトの名無しさん mailto:sage [2007/03/04(日) 10:42:25 ]
- >>282
付けといた方がいいんじゃない?mutexのメモリバリアでcpuキャッシュの同期は取れても スタックやレジスタに積まれたままだったら意味ないしね。
- 285 名前:デフォルトの名無しさん mailto:sage [2007/03/04(日) 11:17:03 ]
- >>283
設計上はウィークメモリオーダリングということなので、OoOあり〜の、コヒーレンシキャッシュは信用できね〜のです。 今のところ実装上はx86系のWindows上ではストロングメモリオーダリングのみ。 Itaniumは構成によってウィークメモリオーダリングもある得るそうです。
- 286 名前:デフォルトの名無しさん mailto:sage [2007/03/04(日) 11:51:52 ]
- ところが、CLR2.0では書き込みオーダは保証されてて、
今後もそうだと約束されてるらしい。 それはおいといて、よく理解できてないのが、 書き込みスレッドでメモリバリアを実行した場合、 読み込み前のメモリバリアは必要なのかどうか。 あるメモリ領域に書き込みしてメモリバリア実行、その後完了フラグセット。 別スレッドで完了フラグを確認してからメモリ領域を読み込みってときに、 完了フラグ確認後にメモリバリアは必要なのかどうか。 なんとなく読み込み順が保証されないから必要な気もするんだが、 .NETのメモリバリア命令はフルメモリバリアだから不要?ってのも見た。 .NETのメモリバリアは別プロセッサの読み込みキャッシュもクリアして かつJITの最適化とかで先読みとかがおこらないなら大丈夫なんだと思うんだけど この方面素人なのでいまいちよく分からない。
- 287 名前:デフォルトの名無しさん mailto:sage [2007/03/04(日) 11:53:25 ]
- メモリバリアの説明には、このプロセッサ上でキャッシュをフラッシュするとかって説明になってんだよね…
- 288 名前:デフォルトの名無しさん mailto:sage [2007/03/04(日) 13:04:32 ]
- Itaniumだと、そもそもout of orderしないですな。
命令の並べ替えや並列化はすべてコンパイラの仕事だ。
- 289 名前:デフォルトの名無しさん mailto:sage [2007/03/04(日) 13:11:11 ]
- だからこそ その辺の事情は本来プログラムで意識したくないよな・・・
DCLの欠点なんて最たるものだし
- 290 名前:デフォルトの名無しさん mailto:sage [2007/03/04(日) 17:17:43 ]
- >>282
メモリバリアだから必要ないという認識では、ちょっと違うね。 関数呼び出しをまたいでグローバル変数をキャッシュできないから volatileが必要ないというのが本質。 変数をレジスタ等にキャッシュしていないからこそ、メモリバリアが有効になる。 仮にlockやunlockをインライン展開できるようなコードで実装できたとすると while() { lock(); i = i + 1; unlock(); } はvolatileが無いと危険かもしれない。
- 291 名前:デフォルトの名無しさん mailto:sage [2007/03/04(日) 19:41:48 ]
- >>290
それは本質じゃなく単なる実装の話だと思います。 たとえばmsvc++などは次の理由からそういう実装になっています。 現在のx86系WindowsはOoOはやっててもアプリからは見えないハード的な仕掛けになっていますし、 コヒーレントキャッシュもある前提なのでキャッシュによる不整合もありません。 x86はレジスタの数が少ないので関数呼び出しのタイミングで変数をメモリ上に書き出します。 たとえばpthreadのmutexではvolatileは不要とドキュメントにあります。 すべてのコンパイラがそうなってるかどうかは分かりませんが、少なくともスレッド系のライブラリと一体で 提供されている環境ではサポートされているはずです。
- 292 名前:デフォルトの名無しさん mailto:sage [2007/03/04(日) 20:23:08 ]
- >>291
インライン展開できない関数を呼ぶ前は、x86であろうと無かろうと 非ローカル変数をキャッシュできないよ。 レジスタの数が問題なのではなく、非ローカルな変数は呼び出した先で 更新される可能性があるから。
- 293 名前:デフォルトの名無しさん mailto:sage [2007/03/04(日) 21:03:48 ]
- あと、ローカル変数でも、アドレスを取って他の関数に渡している場合に
その前と後で変数の中身が変更される可能性は、コンパイラも考慮しているはず。 だから例えば>>255のlockや>>272のpにはvolatile不要なはず。 もちろん、>>255のinitializedには必要だけどね。 で、pthread_mutex_tも、アドレスを取って渡すのだからvolatile不要、 という考え方でも充分かもしれない。 ただし、アドレスを取って呼び出した関数から戻った後に 変数の中身が他のスレッドによって変更される可能性は考慮されないので レジスタにキャッシュされるかもしれない。 それが問題になる可能性がある(コードで中身を参照している)ならば volatileが必要になるね。
- 294 名前:デフォルトの名無しさん mailto:sage [2007/03/04(日) 21:29:48 ]
- >>292
確かにそこは例えが悪かったので取り消します。 (PGOのような広域のインライン展開のことを考えていたのですが論旨に合わないようです) 言いたかったのは同期関数の呼び出しのタイミングで 偶然レジスタとメモリの同期が取られているという話ではなく、 メモリバリア実現の属性のひとつとして関数の呼び出し時にレジスタとメモリの同期が とられるという仕組みが利用されてるということです。 だから、レジスタとメモリの同期以外にCPUキャッシュ間の同期やOoOの調整が必要ならば その処理が同期関数に含まれていなければならないと考えているわけです。
- 295 名前:デフォルトの名無しさん [2007/03/05(月) 18:53:41 ]
- ____
/ \ / ─ ─\ / (●) (●) \馬鹿ばっか | (__人__) | \ ` ⌒´ / ノ \ /´ ヽ | l \ ヽ -一''''''"~~``'ー--、 -一'''''''ー-、. ヽ ____(⌒)(⌒)⌒) ) (⌒_(⌒)⌒)⌒))
- 296 名前:デフォルトの名無しさん [2007/03/05(月) 22:57:17 ]
- volatile旋風スゴス
- 297 名前:デフォルトの名無しさん mailto:sage [2007/03/10(土) 22:35:07 ]
- 質問です。
while ( count > 1 ){ pthread_cond_wait( &cond_t, &mutex ); } この場合、条件変数と呼ばれるものはcountですか? それともcond_tになるのでしょうか? また、countのチェックにifは使ってはならない。と言われたのですが、 なぜだか解りません。 上記の部分と、 while (1){ if( count > 1 ) pthread_cond_wait(ry); } は同じだと思うのですが・・・ よろしくお願いします
- 298 名前:デフォルトの名無しさん mailto:sage [2007/03/10(土) 22:51:41 ]
- >>297
while (1) { if( ! (count > 1) ) break; pthread_cond_wait(ry); } と同じだと思う。
- 299 名前:デフォルトの名無しさん mailto:sage [2007/03/10(土) 23:04:21 ]
- >>298
そうでした。すんません
- 300 名前:デフォルトの名無しさん mailto:sage [2007/03/10(土) 23:33:31 ]
- > 条件変数と呼ばれるものはcountですか?それともcond_tになるのでしょうか?
条件変数はcond_t。!(count>1)は述語。 > countのチェックにifは使ってはならない。と言われたのですが、 言った本人に聞けばいいと思う。いけないってことは無いと思う。 pthread_mutex_lock(&mutex); while (!pred(ry)) pthread_cond_wait(&cond, &mutex); pthread_mutex_unlock(&mutex); というのが定型パターンの予感はするんで、 その人にとって奇怪なコーディングするなという意味かもしれん。
- 301 名前:デフォルトの名無しさん mailto:sage [2007/03/11(日) 08:33:14 ]
- ありがとうございます。
countは述語っていうのですか。知りませんでした。 >ifでんでん 後でもう一度聞いてみます。
- 302 名前:デフォルトの名無しさん mailto:sage [2007/03/11(日) 11:25:05 ]
- でんでんってなんだ。云々(うんぬん)と言いたいのか、わざとボケてるのかどっちだ。
- 303 名前:デフォルトの名無しさん mailto:sage [2007/03/11(日) 12:35:43 ]
- >>302
単なる2chのジャーゴンだから気にするな
- 304 名前:デフォルトの名無しさん mailto:sage [2007/03/11(日) 14:17:43 ]
- countが述語なんじゃなくて
"count>1"が述語 countは単なる変数
- 305 名前:301 mailto:sage [2007/03/11(日) 15:38:51 ]
- >>304
"count>1"で、述語。ですか。解りました。 ありがとうございます。 >>でんでん "うんぬん"で"云々"ですか。初めて知りました ゆとり年代より一つ上なはずなんだけどゆとりでごめんなさい
- 306 名前:300 mailto:sage [2007/03/11(日) 15:43:08 ]
- ごめん。!(count>1)でなく、count>1だった。
301に幸あらんことを。
- 307 名前:デフォルトの名無しさん mailto:sage [2007/03/11(日) 15:43:39 ]
- 俺がかつて1日だけ流行らそうとしてばら撒いてたでんでんが意外な影響を。
- 308 名前:デフォルトの名無しさん mailto:sage [2007/03/11(日) 16:04:43 ]
- 「云々」を「でんでん」ってことは
「云」を「でん」と読んでるって事だよな。 俺、そもそも「云」という漢字、単独でどう読むか知らないのだが。
- 309 名前:デフォルトの名無しさん mailto:sage [2007/03/11(日) 16:29:44 ]
- >>308
「ウン」でしょ。
- 310 名前:デフォルトの名無しさん mailto:sage [2007/03/11(日) 16:37:38 ]
- 伝が“でん”だからなあ
- 311 名前:デフォルトの名無しさん mailto:sage [2007/03/11(日) 20:45:06 ]
- 雲が「うん」と読まれることには頓着しないらしい。
- 312 名前:デフォルトの名無しさん mailto:sage [2007/03/11(日) 22:22:20 ]
- ワンタン
雲呑
- 313 名前:デフォルトの名無しさん mailto:sage [2007/03/12(月) 00:36:16 ]
- うーんぬんむーしむし、かーたつむりー
- 314 名前:デフォルトの名無しさん [2007/03/16(金) 09:25:59 ]
- ____
/ \ / ─ ─\ / (●) (●) \ 「テラワロスwwwwwwwうぇうぇwwww」・・・・と | (__人__) | ________ \ ` ⌒´ ,/ .| | | ノ \ | | | /´ カタ. | | | | l カタ | | | ヽ -一ー_~、⌒)^),-、 | |_________| ヽ ____,ノγ⌒ヽ)ニニ- ̄ | | | ____
- 315 名前:デフォルトの名無しさん [2007/03/20(火) 00:12:35 ]
- ごめん書籍いいでしょっていわれてるけれど
マルチスレッドの勉強する本をおしえてほしいの
- 316 名前:デフォルトの名無しさん mailto:sage [2007/03/20(火) 00:32:02 ]
- マルチスレッドについて本で得られるものは1%もない。
といっては見もふたもないので、もう少し具体的にマルチスレッドで何をしたいの? OSは?マルチスレッドアプリ?APIがしりたい?それともカーネルの実装(はないよな)?
- 317 名前:デフォルトの名無しさん [2007/03/20(火) 15:54:59 ]
- Unix 方面の人は「実践マルチスレッドプログラミング」
Win32の人は「Win32マルチスレッドプログラミング」 当り前のことが当たり前に書かれてるだけで、 別にいいも悪いもないけど。 このあたりに出てくるような概念、問題、手法については常識として理解した上で、 新しい手法やOS/CPU/言語毎のメモリモデルなどについての知識を深めると、 volatile 論議とかで無駄に遊べる。
- 318 名前:デフォルトの名無しさん mailto:sage [2007/03/20(火) 23:15:04 ]
- >>315
Java使いなら↓は超オススメ。 www.amazon.co.jp/Java-Concurrency-Practice-Brian-Goetz/dp/0321349601 邦訳版もあるよ。
- 319 名前:デフォルトの名無しさん [2007/03/21(水) 00:27:18 ]
- >>317
素朴な疑問 > Unix 方面の人は「実践マルチスレッドプログラミング」 > Win32の人は「Win32マルチスレッドプログラミング」 この辺を読めば volatile 最強って言い切れるようになるんですか?
- 320 名前:デフォルトの名無しさん mailto:sage [2007/03/21(水) 03:30:37 ]
- 317をもう一度よく読んだほうがいいんじゃない?
- 321 名前:デフォルトの名無しさん mailto:sage [2007/03/21(水) 04:34:08 ]
- 自作自演の可能性
- 322 名前:デフォルトの名無しさん mailto:sage [2007/03/21(水) 13:51:09 ]
- volatile厨を論破するのはそんなに簡単じゃないよ。
- 323 名前:デフォルトの名無しさん mailto:sage [2007/03/21(水) 15:55:04 ]
- NG登録するだけだし
- 324 名前:デフォルトの名無しさん [2007/03/24(土) 10:03:31 ]
- Win32の本ってオライリーのやつのことでいいの?
- 325 名前:デフォルトの名無しさん mailto:sage [2007/03/24(土) 15:56:09 ]
- >>315
並行プログラミングの原理―プロセス間通信と同期への概念的アプローチ (単行本)
- 326 名前:デフォルトの名無しさん [2007/03/27(火) 14:50:58 ]
- ____
/ \ /\ キリッ . / (ー) (ー)\ / ⌒(__人__)⌒ \ volatile厨を論破するのはそんなに簡単じゃないよ。 | |r┬-| | \ `ー'´ / ___ / \ クスクスッ /ノ \ u. \ !? / (●) (●) \ | (__人__) u. | \ u.` ⌒´ / ____ / \!?? / u ノ \ クスクスッ / u (●) \ | (__人__)| \ u .` ⌒/
- 327 名前:デフォルトの名無しさん [2007/03/27(火) 22:33:12 ]
- Javaのsynchronizedとwaitとnotifyに関する質問なんだが
www.javaworld.jp/technology_and_programming/-/10941-5.html ここの class Buffer { private int value; private boolean isEmpty = true; public synchronized void putValue(int v) { while (!isEmpty) { try { wait(); } catch (InterruptedException e) { } } notifyAll(); isEmpty = false; value = v; } public synchronized int getValue() { while (isEmpty) { try { wait(); } catch (InterruptedException e) { } } notifyAll(); isEmpty = true; return value; } } これがどうして動くのか分からん。 あるスレッドがgetValueに入ってる間は、ほかのスレッドは getValueにもputValueにも入れないんじゃないのか
- 328 名前:デフォルトの名無しさん mailto:sage [2007/03/27(火) 22:34:13 ]
- すまんソースコードが見づらくなってしまった。
リンク先を見てくれ。
- 329 名前:デフォルトの名無しさん mailto:sage [2007/03/27(火) 22:52:21 ]
- >>327
前のページで説明されてる。
- 330 名前:デフォルトの名無しさん mailto:sage [2007/03/27(火) 22:53:08 ]
- ttp://sdc.sun.co.jp/java/docs/j2se/1.4/ja/docs/ja/api/java/lang/Object.html#wait()
の二段落目を理解できない無能?
- 331 名前:デフォルトの名無しさん mailto:sage [2007/03/27(火) 23:05:42 ]
- すまんかった。
とんくす
- 332 名前:デフォルトの名無しさん [2007/03/28(水) 08:53:09 ]
- ____
/ \ /\ キリッ . / (ー) (ー)\ / ⌒(__人__)⌒ \ の二段落目を理解できない無能? | |r┬-| | \ `ー'´ / ___ / \ クスクスッ /ノ \ u. \ !? / (●) (●) \ | (__人__) u. | \ u.` ⌒´ / ____ / \!?? / u ノ \ クスクスッ / u (●) \ | (__人__)| \ u .` ⌒/
|

|