- Javaメモリモデルで必要とされる初期化の安全性を説明できる人はいますか?
- 最終フィールドは、初期化の安全性を達成するのにどのように役立ちますか?
- 初期化の安全性を確保する上でコンストラクターはどのような役割を果たしますか?
2 に答える
初期化の安全性は、完全に構築された (初期化された) 状態のオブジェクトを外部スレッドから参照できるようにします。前提条件は、オブジェクトを時期尚早に公開しないことです。そのコンストラクターで。これが保証されると、JMM は として宣言されたフィールドに対して特定の動作を要求しますfinal
。まず、すべてのfinal
オブジェクト フィールドは、完全に初期化された状態で外部スレッドから見えることが保証されます。これは、思ったほど簡単ではありません。
クラスを考えてみましょう:
class A {
List list;
A() {
list = Arrays.asList(some init expressions that adds 10 elements to list);
}
}
list
ofインスタンスにアクセスするスレッドはA's
、デフォルトでは、そのリスト内の 10 個の要素を表示することが保証されていません。実際、このスレッドlist
はnull
. ただし、list
が 宣言さfinal
れている場合、JMM の要求に従って、list
は常に 10 個の要素で初期化されているように見える必要があります。
第 2 に、この初期化保証はfinal
フィールド自体に限定されず、それによって参照されるすべてのオブジェクトに再帰的に拡張されます。たとえばlist
、上記の例の がリスト自体のリストである場合、外部スレッドは内部リストが完全に初期化されていると見なすことが保証されます。
synchronized
メモリの可視性でこの安全性を達成するためにどこにも使用していないことに注意してください(発生前の関係)。
1. 初期化の安全性により、適切に構築された不変オブジェクトを、同期を使用せずにスレッド間で安全に共有できます。データ競合を使用してパブリッシュした場合でも同様です。
2. final フィールド、初期化の安全性を持つオブジェクトは、そのオブジェクトへの参照の初期ロードで構築のどの部分も並べ替えられないようにします。