いやあ、こんな素晴らしい本をタダでいただけるなんて素晴らしいですね。
ありがとうございます > 高林様、オラ入りー様
なにかhyoshiokさんの所では、若干厳しめのレビューをされてるみたい。
たぶん、NHKに取り上げられた 女子大生のブログ炎上とかの記事をみて、ベタ褒めすると炎上する日本のBLOG力学に思うところがあったに違いない。
と、無理やり時事ネタに絡ませつつ、おもしろいから、ここは一発絡んでおこう。
いやいや。
#94の例では lock_array[me] を変更するのは自分だけで、lock_array[other]を変更するのは相手だけなのでxchgは必須じゃないですよ。
(lock_array[me]を変更するのが自分だけである以上、変更直前の値はかならず自分が前回設定した値だから、チェックするまでもない)
”double checked locking”あたりで検索するといろいろと出てきますよ。
無理やり要約すると
・パターンハッチング(ジョン・ブリシデス著 ビアソン)にてdouble checked lockingパターンが紹介される
・JavaでJavaVMのメモリオーダーが原因でdouble checked lockingパターンを使うとある種のJIT VMでうまく動かない事が報告され、話題になる
・C#はvolatileにメモリオーダー的な意味を追加して、この問題を回避
・Javaもそれに追従して、volatileの意味を改定
・実は元々のC++にも同じ問題があるのだけれど、完全に置いてきぼり(n'ω'`) <--今、ここ
正味の話、たとえば、int変数1個writeするだけだと、strong memory orderだと、pthread_mutex_lockかけなくても正しいけれど、現実のプロセッサはそうではなく、かつ、そのようなメモリオーダーの話が「一般のプログラマには難しすぎるから」というよく分からない理由でmutexとかの説明にマトモに解説されていないので、似たようなバグが次々と量産されているという感じ。
オイラ、元々組み込み屋さんだから、こういうタイミング問題は何回も痛い目にあっているので。
まだ、全部読んでないのでちゃんとした書評はあとで書こうと思うけども、今回はこんなところで。
P.S.
と、ここまで書いてから#94は、double checked locking パターンを題材に書き直せば作為的度が減って、よりグッドになりそうな悪寒がしてきた。
うーん、惜しい。
↓ 初回限定カバーはこんなのらしい
ありがとうございます > 高林様、オラ入りー様
なにかhyoshiokさんの所では、若干厳しめのレビューをされてるみたい。
たぶん、NHKに取り上げられた 女子大生のブログ炎上とかの記事をみて、ベタ褒めすると炎上する日本のBLOG力学に思うところがあったに違いない。
と、無理やり時事ネタに絡ませつつ、おもしろいから、ここは一発絡んでおこう。
#94「プロセッサのメモリオーダリングに注意」の例のプログラムだが、これはメモリオーダリングの例ではなくてアトミックな交換(xchg)が出来ていない例なのではないだろうか?
いやいや。
#94の例では lock_array[me] を変更するのは自分だけで、lock_array[other]を変更するのは相手だけなのでxchgは必須じゃないですよ。
(lock_array[me]を変更するのが自分だけである以上、変更直前の値はかならず自分が前回設定した値だから、チェックするまでもない)
アプリケーションレベルでメモリオーダリングに注意しなければいけない例というのはあまり思いつかなかったのでもし適切な例があればご教示いただきたいところである。
”double checked locking”あたりで検索するといろいろと出てきますよ。
無理やり要約すると
・パターンハッチング(ジョン・ブリシデス著 ビアソン)にてdouble checked lockingパターンが紹介される
・JavaでJavaVMのメモリオーダーが原因でdouble checked lockingパターンを使うとある種のJIT VMでうまく動かない事が報告され、話題になる
・C#はvolatileにメモリオーダー的な意味を追加して、この問題を回避
・Javaもそれに追従して、volatileの意味を改定
・実は元々のC++にも同じ問題があるのだけれど、完全に置いてきぼり(n'ω'`) <--今、ここ
正味の話、たとえば、int変数1個writeするだけだと、strong memory orderだと、pthread_mutex_lockかけなくても正しいけれど、現実のプロセッサはそうではなく、かつ、そのようなメモリオーダーの話が「一般のプログラマには難しすぎるから」というよく分からない理由でmutexとかの説明にマトモに解説されていないので、似たようなバグが次々と量産されているという感じ。
オイラ、元々組み込み屋さんだから、こういうタイミング問題は何回も痛い目にあっているので。
まだ、全部読んでないのでちゃんとした書評はあとで書こうと思うけども、今回はこんなところで。
P.S.
と、ここまで書いてから#94は、double checked locking パターンを題材に書き直せば作為的度が減って、よりグッドになりそうな悪寒がしてきた。
うーん、惜しい。
↓ 初回限定カバーはこんなのらしい
コメント
コメント一覧 (7)
って、本物は普通のカバーじゃないですか~。し、しまったー。
やはり、読む前に感想を書くのは遺憾ですなぁ
http://www-06.ibm.com/jp/developerworks/java/020726/j_j-dcl.html
というのがあったので、読んでみた。
で質問なんですが、リスト4の
synchronized(Singleton.class) { //1
if (instance == null) //2
instance = new Singleton(); //3
}
で、3の実行が終わるまえ(?)にスレッドが切り替わるってのはありなんすか?
つまり、
mem = allocate(); //Allocate memory for Singleton object.
instance = mem; //Note that instance is now non-null, but
//has not been initialized.
ctorSingleton(instance); //Invoke constructor for Singleton passing
//instance.
メモリはアロケートしたけど、コンストラクターは呼ばれていない状況でスレッド切り替わっちゃうんですか?
synchoronized{}というのを分かっていないので変な事聞いているのかもしれないっすが。
おおお、コメントありがとうございます。
synchronized(lock){} とは
"{" の段階でロック変数lock をaquire, "}"の段階でrelease。
だと思ってください。
#JavaではすべてのObjectがlock操作を持つのでlockにはobjectっぽいものは何でも渡せます
だから、スレッドの切り替わり自体は何も妨げられません。
同じlockを監視しているブロックには2つのスレッドは同時に入れないので、普通はそれで十分
で、上記文献に戻ると、以下を見てください
1: if (instance == null){
2: synchronized(Singleton.class) { //1
3: if (instance == null) //2
4: instance = new Singleton(); //3
5: }
6: }
7: }
8: instance.someMethod();
とかなっていたとします。
(見やすくするために行番号をつけました)
スレッドA: 行番号1を実行
スレッドA: 行番号2を実行
スレッドA: 行番号3を実行
スレッドA: 行番号4の代入を実行
スレッドB: 行番号1がnullではないので、行8へ
スレッドB: 初期化されていないオブジェクトに対してメソッドコール(ぼーん!)
がありえるよー。
と言っているようです。
回答になっていれば幸いですm(_ _)m