argius note

プログラミング関連

volatile修飾子

今の私ではたぶん上手く説明できないので復習。理解した内容を咀嚼して書いてみる。

同期処理において情報を共有するフィールドで、頻繁に変更があることを示す。volatileを指定しないフィールドの値は、あるスレッドが変更した内容が即時に(または永久に)反映されるとは限らないので、別のスレッドから変更を確実に確認することができない。
実際、実装においてそのフィールドの値はスレッドが確保した作業メモリにコピーされ、その作業メモリ上で変更を行うため、書き戻す頻度によっては最新の状態が見えないことになる。
long,double以外のプリミティブ型(32bit以下でOK?)はatomicであり、異なるスレッド間でも同期を取らずに共有することが出来る。long,doubleおよび参照型は、atomicとはならない。volatileを指定することで、即座に書き戻しをするようになる。

こんなところでしょうか。しかし、後半のatomicについては以下のような問題がありました。
http://d.hatena.ne.jp/muimy/20040129/p6 (コメント欄から引用)

count++/count--をスレッドセーフにするにはvolatileでは駄目で,synchronizedメソッド/文を使う必要があるはずです.count++はcountのロード,加算,ストアの三つの処理から構成されており,少なくともこれ全体をatomicに処理しないかぎりスレッドセーフにはなりません.volatileでできるのはロードやストアなどの個々の処理をatomicに処理することまでで,count++全体はatomicにはならないはずです.

つまり、

int a = count; // countはintフィールド
a = a + 1;
count = a;

だってことかな? 再現性は極低とのことですが、そうでしょうね。私はちゃんと仕様を調べてないですが、注意すべき点ではありますよね。