ここで次のコードを見つけました:http://en.wikipedia.org/wiki/Double-checked_locking#Usage_in_Java
これが機能しない特定のケースがある理由を理解しようとしています。「微妙な」問題の説明を読みました。それを使用volatile
すると問題が解決しますが、少し混乱しています。
// Broken multithreaded version
// "Double-Checked Locking" idiom
class Foo {
private Helper helper = null;
public Helper getHelper() {
if (helper == null) {
synchronized(this) {
if (helper == null) {
helper = new Helper();
}
}
}
return helper;
}
// other functions and members...
}
基本的に、その時点で「部分的に」構築される可能性があるためhelper == null
、ブロック内のチェックが失敗する可能性があるという事実のために、これが失敗すると想定するのは正しいですか?オブジェクトが部分的に構築されている場合、synchronized
Javaはnullを返しませんか?それが問題ですか?
とにかく、ダブルチェックロックを行うのは良い習慣ではないことは知っていますが、理論的には、上記のコードが失敗する理由と、volatile(およびローカル変数の割り当ての追加)がこれを修正する理由に興味がありましたか?これが私がどこかから得たコードです。
// Double-check idiom for lazy initialization of instance fields
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;
}
これについてはすでに1000件の投稿があることは知っていますが、説明では1.5以降のメモリモデルの変更について言及しているようで、それが何に関係しているのかもよくわかりません:-(。
よろしくお願いします!