私は、Effective Java(第2版)の項目71「怠惰な初期化を慎重に使用する」を進めています。このコード(283ページ)を使用して、インスタンスフィールドの遅延初期化にダブルチェックイディオムを使用することをお勧めします。
private volatile FieldType field;
FieldType getField() {
FieldType result = field;
if (result == null) { //First check (no locking)
synchronized(this) {
result = field;
if (result == null) //Second check (with locking)
field = result = computeFieldValue();
}
}
return result;
}
だから、私は実際にいくつかの質問があります:
field
同期ブロックで初期化が行われるのに、なぜ揮発性修飾子が必要なのですか?この本は、このサポートテキストを提供しています。「フィールドがすでに初期化されている場合はロックがないため、フィールドが揮発性であると宣言することが重要です」。したがって、フィールドが初期化されるとfield
、他の同期がない場合に、複数のスレッドで一貫したビューが保証されるのはvolatileだけですか?もしそうなら、なぜgetField()を同期しないのですか、それとも上記のコードがより良いパフォーマンスを提供するのですか?このテキストは、不要なローカル変数、
result
を使用して、「field
すでに初期化されている一般的なケースで1回だけ読み取られるようにする」ことで、パフォーマンスを向上させることを示唆しています。削除された場合、すでに初期化されている一般的なケースでresult
は、どのようfield
に複数回読み取られますか?