次のコードはスレッドセーフと見なされますか、つまり、リストへの書き込みはリストへの読み取りよりも前に発生することが保証されていますか? これが Java メモリ モデルで安全と見なされるかどうかを理解しようとしてきましたが、不明です。
synchronized
基本的なフロー分析を通じて、考えられるすべてのスレッドが以下のループに到達する前に初期化ブロックを通過する必要があることが保証されているように見えますがfor
、そのリストの反復は決定論的でスレッドセーフでしょうか? 以下のリストを使用する前に初期化が行われることが保証されているかどうかはわかりません。
これがクラス内の唯一のメソッドであると仮定します。同期ブロック内で反復を移動するとスレッドセーフが保証されることはわかっていますが、この構造が安全かどうかを知りたいと思っています。
また、リストがクラスを決してエスケープしないと仮定します。
Java メモリ モデルは、こちらの JLS で説明されています: http://docs.oracle.com/javase/specs/jls/se7/html/jls-17.html#jls-17.4
private List<Foo> list;
private final Object monitor = new Object();
public void bar() {
synchronized (monitor) {
if (list == null) {
list = new ArrayList<>();
list.add(...); // expensive operation
list.add(...); // expensive operation
list.add(...); // expensive operation
}
}
for (Foo foo : list) {
// do something with foo
}
}