[過去ログ]
マルチスレッドプログラミング相談室 (986レス)
マルチスレッドプログラミング相談室 http://toro.5ch.net/test/read.cgi/tech/997345868/
上
下
前次
1-
新
通常表示
512バイト分割
レス栞
抽出解除
レス栞
このスレッドは過去ログ倉庫に格納されています。
次スレ検索
歴削→次スレ
栞削→次スレ
過去ログメニュー
444: デフォルトの名無しさん [sage] 02/08/31 21:37 (バージョン判定式)が ・何回行っても処理に問題はなく ・スレッドセーフであり ・常に同じ値を返す のであれば、排他制御は必要無い(はず)。 一般には(上記のどれかを満たさないorコストがかかる場合)、Gをvolatileで宣言しておいて void init_G() { if (G == 0) { lock(); if (G == 0) { if (...) { G = 1; } else { G = 2; } unlock(); } } } のように、初期化が必要になる可能性がある場合のみ、 ロックしてから再度判定する場合が多いと思う。 http://toro.5ch.net/test/read.cgi/tech/997345868/444
445: 442 [sage] 02/08/31 23:09 >>443,444 どうもありがとうございます。 基本的な考えは間違っていないようで、安心しました。 > 書いてあるプログラムも、「いったん判断式を評価したら、二度と評価しない」 > となっているので、その点もよい。 この理由がよくわかりませんでした。 私が if(G == 0) を付けたのは、 「判断式を評価する時間がもったいないから」というだけで 深い意味はなかったのですが、 他にも意味があるのでしょうか? (判断式を何度評価しても動作に支障がない場合) また、444 さんのコードの意味もよくわかりません。 void init_G() { lock(); if(G == 0) { if (...) G = 1; else G = 2; } unlock(); } だけではまずいでしょうか? lock() にかかる時間的コストを考慮? lock() と unlock() が対になっていない点も疑問です。 http://toro.5ch.net/test/read.cgi/tech/997345868/445
446: 444 [sage] 02/09/01 00:34 ごめん。unlockの位置は{}とインデントをつけた時にミスった。 G==0を2度やっているのは、コストの問題。 本当にlockする必要があるのは最初だけで、それ以降は常にG!=0なのだから、 そのためだけに毎回lockするのは時間的に無駄だから。 例えば、Singletonなんかでインスタンスを初期化/取得する場合でも、 毎回実行する部分は出来るだけ軽くすべきであり、 最初以外はlockせずに値を取得出来るようにするため。 http://toro.5ch.net/test/read.cgi/tech/997345868/446
447: 444 [sage] 02/09/01 00:36 よく見たら、 >lock() にかかる時間的コストを考慮? って書いてあった。その通りです。 http://toro.5ch.net/test/read.cgi/tech/997345868/447
448: デフォルトの名無しさん [sage] 02/09/01 01:12 >>444 そのコードだとGをvolatile宣言する必要はナシ。 そもそも、volatile宣言された変数へのアクセスって 意外とコスト高なんで注意すべし。 ちなみに>>444のアルゴリズムはDouble-Checked Lockingと 呼ばれているんだが、場合によってはうまく動かないことが 知られている。 具体的には、初期化の対象がatomicなアクセスが保証されている primitive型の変数ではなく、緩いメモリモデルを採用している プラットホーム上で動かした場合に、うまく動かない可能性がある。 緩いメモリモデルの例としてはJava memory modelとかがあるから 参考として以下の記事なんかを読んでおくのもいいよ。 http://www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html http://toro.5ch.net/test/read.cgi/tech/997345868/448
449: 444 [sage] 02/09/01 01:36 どうもありがとう。 C/C++でも、volatileは必要無いのかな? つまり、lockした後の再判定時に、コンパイラの最適化で レジスタ等にキャッシュされた値を読んでしまうのを防ぐ必要があるかなと。 コスト的にも、C/C++なら、スタック以外の変数(の読み出し)にかかるコストは、 volatileでもそう変わらないと思ったし(読み出しが一回だけの場合)。 Javaなら、インスタンス変数をキャッシュする関係で差がつくのはわかるけど、 >>444は元々C/C++を想定していたから。 ただ、スタック上の変数の場合は、C/C++でもレジスタ割り付けの関係で差が付きそう。 あと、問題があることは知らなかった。 操作対象がatomicに操作できなくても、判定するためのフラグを用意すれば 一般的に解決できる問題なのかな? とりあえず、リンク先読んでみる。 http://toro.5ch.net/test/read.cgi/tech/997345868/449
450: 444 [sage] 02/09/01 02:19 とりあえず、マルチプロセッサ環境において、 ・コンストラクタが実行されて初期化されるまでの間 ・(C/C++などのCPUキャッシュの同期が保証されていないものでの)メモリからの読み出し時 に問題があることはわかった。 その他はまだよく理解出来てないけど。 http://toro.5ch.net/test/read.cgi/tech/997345868/450
451: 442 [sage] 02/09/01 03:01 >>444 どうもありがとうございます。 おかげ様で大変よくわかりました。感謝感謝です。 今度は >>448の volatile宣言の必要がないというのがわかりません。 (444さんと同じ考えですが) volatileが無いと、 lock とunlock が通常の関数呼び出しとして実装されている なら大丈夫としても、 仮にこれらがインライン展開される関数やマクロだった場合に、 ・lockの直後のif文で G がメモリから再ロードされるかどうか ・更新後の Gの値がunlockの前でメモリに書き込まれるかどうか が保証されないのでは? と思えます。 http://toro.5ch.net/test/read.cgi/tech/997345868/451
メモ帳
(0/65535文字)
上
下
前次
1-
新
書
関
写
板
覧
索
設
栞
歴
スレ情報
赤レス抽出
画像レス抽出
歴の未読スレ
AAサムネイル
Google検索
Wikipedia
ぬこの手
ぬこTOP
0.044s