記事: Javaの理論と実践: Javaメモリ・モデルを修正する 第2回
メモ:
- 可視性の問題
- すぐに他のスレッドの変更が見えるとは限らない
- これを保証するのがメモリモデル
- volatile, synchronized, final のメモリセマンティクスを決定している
- 同期化ブロックと可視性
- スレッドが同期化ブロックを出る時は、ローカルキャッシュをはき出す
- スレッドが同期化ブロックに入る時は、ローカルキャッシュを無効化
- volatile に対する新たな保証
- 旧:volatile 変数への操作のみ順序を保証していた
- 新:「スレッド A が volatile 変数 V に書き込み、スレッド B が V から読み出す時、V に書き込む時に A から見えるどんな変数値も、Bから見えることが保証される」
- 旧モデルよりもアクセスコストが高くなったが、意味体系がより有用になった(番兵としての利用が可能になった)
- 事前発生 (happens-before)
- 特定の操作の部分配関係を保証するための、happens-before という関係を非公式に定義
- データ・レース(Data races)
- ある変数を複数のスレッドの読み書きが happens-before 関係によって配列されていない場合、Data race が発生する
- 古いメモリモデルでは double-checking lock を解決しない
- volatile 以外はリオーダーされて可視性が保証されない
- 新しいメモリモデルは、double-checking lock を解決するが、volatile アクセスが高くなってるから、double-checking lock は使わない方がよい
- Initialize on demand holder を使うべき
- クラス初期化の一部としての操作は、すべてのスレッドから可視である
- final フィールドはコンストラクト後、可視性が保証される
- コンストラクタでの final field への書込みと、別のスレッドの共有参照の最初ののロードとの間に heppens-before に似た関係がある
- ただし、コンストラクタ内で自身の参照が漏洩しないことが条件(『Javaの理論と実践: 安全な構築のテクニック』のメモ - 王様の美術館)
- まとめ
- volatile のセマンティクスが強化された。ただし、コストは増加した。
- final field のセマンティクスが強化された。不変オブジェクトの実用性が高くなった。
感想
同じことが何回も書かれているのだが、こうやって繰り返し学習することで、どんどん知識が定着している気がする。