Javaメモリモデルによる「効果的に不変のオブジェクト」の動作を正しく理解していることを確認したいと思います。
事実上不変として公開したい可変クラスがあるとしましょう。
class Outworld {
// This MAY be accessed by multiple threads
public static volatile MutableLong published;
}
// This class is mutable
class MutableLong {
private long value;
public MutableLong(long value) {
this.value = value;
}
public void increment() {
value++;
}
public long get() {
return value;
}
}
次のことを行います。
// Create a mutable object and modify it
MutableLong val = new MutableLong(1);
val.increment();
val.increment();
// No more modifications
// UPDATED: Let's say for this example we are completely sure
// that no one will ever call increment() since now
// Publish it safely and consider Effectively Immutable
Outworld.published = val;
問題は次のとおりです。Javaメモリモデルは、すべてのスレッドが持っている必要があることを保証しますOutworld.published.get() == 3
か?
Java Concurrency In Practiceによると、これは正しいはずですが、間違っている場合は訂正してください。
3.5.3。安全な出版イディオム
オブジェクトを安全に公開するには、オブジェクトへの参照とオブジェクトの状態の両方を同時に他のスレッドに表示する必要があります。適切に構築されたオブジェクトは、次の方法で安全に公開できます。-
静的初期化子からオブジェクト参照を初期化する。
-それへの参照を揮発性フィールドまたはAtomicReferenceに保存します。
-それへの参照を適切に構築されたオブジェクトの最終フィールドに格納します。または
-ロックによって適切に保護されているフィールドに参照を保存します。3.5.4。効果的に不変のオブジェクト
安全に公開された効果的に不変のオブジェクトは、追加の同期なしで任意のスレッドで安全に使用できます。