熱心なインスタンス化では、フィールドの参照を共有するための明示的な同期は必要ありません。これは、JVMがクラス読み込みメカニズムの一部としてすでにフィールドの参照を処理しているためです。
より詳細に説明すると、クラスがスレッドで使用できるようになる前に、クラスがロードされ、検証され、初期化されます。コンパイラは、静的フィールドの割り当てをこの初期化段階に書き換え、Javaメモリモデルのルールと基盤となるハードウェアアーキテクチャを介して、そのクラスにアクセスするすべてのスレッドがこのバージョンのクラスを確実に認識できるようにします。これは、JVMがハードウェアバリアなどを処理してくれることを意味します。
そうは言っても、熱心な初期化を最終的にマークすることをお勧めします。これにより、意図が明確になり、コンパイラーは、熱心な初期化が変更されないように強制します。もしそうなら、同時実行制御が再び必要になるでしょう。
private static **final** Singleton INSTANCE = new Singleton();
参考までに、興味があれば、Java仮想マシン仕様のセクション5.5でこれについてさらに詳しく説明しています。仕様からのいくつかの選択スニペットは次のとおりです。
*"Because the Java Virtual Machine is multithreaded,
initialization of a class or interface requires careful
synchronization"*
*"For each class or interface C, there is a unique initialization lock LC"*
*9&10) "Next, execute the class or interface initialization method of C"
"If the execution of the class or interface initialization
method completes normally, then acquire LC, label the Class object for
C as fully initialized, notify all waiting threads, release LC, and
complete this procedure normally."*
静的フィールドが設定されるのは仕様のステップ10であり、ロック(LC)を使用して、1つのスレッドのみが初期化を実行し、結果が正しく共有されるようにします。