Javaメモリモデルでは、次のように記述されています。関連するモニターの解放の一部としてスレッドが同期ブロックを終了する場合、JMMはローカルプロセッサキャッシュをメインメモリにフラッシュすることを要求します。同様に、同期ブロックに入るときにモニターを取得する一環として、ローカルキャッシュが無効化されるため、後続の読み取りはローカルキャッシュではなく、メインメモリに直接送信されます。
では、なぜそのコードでインスタンスを揮発性として宣言する必要があるのでしょうか。2番目のスレッドが同期ブロックに入ると、メインメモリに直接移動するからです。
public final class MySingleton {
private static MySingleton instance = null;
private MySingleton() { }
public static MySingleton getInstance() {
if (instance == null) {
synchronized (MySingleton.class) {
if (instance == null) {
instance = new MySingleton();
}
}
}
return instance;
}
}
つまり、別のスレッドが同期ブロックに入り、2番目のチェックを行うと、前述のようにメインメモリから更新されることになっています。