うーん。これを読んだとき、技術的には正しくありませんが、実際にはいくつかの注意事項があります。一度安全に初期化でき、同期せずに複数のスレッドでアクセスできるのは最終フィールドのみです。
遅延初期化スレッドは、さまざまな方法で同期の問題に悩まされる可能性があります。たとえば、クラス自体が完全に初期化されずにクラスの参照がエクスポートされた場合、コンストラクターの競合状態が発生する可能性があります。
プリミティブ フィールドまたはオブジェクトがあるかどうかに大きく依存すると思います。複数のスレッドが初期化を行うことを気にしない場合に、複数回初期化できるプリミティブ フィールドは正常に機能します。ただしHashMap
、この方法でのスタイルの初期化には問題がある場合があります。long
一部のアーキテクチャの値でさえ、複数の操作で異なる単語を保存する可能性があるため、値の半分をエクスポートする可能性がありますがlong
、メモリページを横切ることは決してないので、決して起こらないと思います。
アプリケーションにメモリバリア (ブロックやフィールドへのアクセス) があるかどうかに大きく依存すると思います。悪魔は確かにここの詳細にあり、怠惰な初期化を行うコードは、1 つのコード セットを使用する 1 つのアーキテクチャでは正常に動作し、別のスレッド モデルやほとんど同期しないアプリケーションでは正常に動作する可能性があります。synchronized
volatile
比較として、最終フィールドの良い部分を次に示します。
http://www.javamex.com/tutorials/synchronization_final.shtml
Java 5 の時点で、final キーワードの 1 つの特定の使用法は、同時実行の武器において非常に重要であり、見落とされがちな武器です。基本的に、final を使用して、オブジェクトを構築するときに、そのオブジェクトにアクセスする別のスレッドが、そのオブジェクトを部分的に構築された状態で認識しないようにすることができます。これは、オブジェクトの変数の属性として使用される場合、final がその定義の一部として次の重要な特性を持っているためです。
これで、フィールドが final とマークされていても、それがクラスであれば、クラス内のフィールドを変更できます。これは別の問題であり、これにはまだ同期が必要です。