我无法理解“有效Java”中第71条中的一段代码。关于实例字段的延迟初始化的Double-check习语和单一检查习语:
仔细检查成语
private volatile FieldType field;
FieldType getField() {
FieldType result = field;
if (result == null) {
synchronized(this) {
result == field;
if (result == null)
field = result = computeFieldValue();
}
}
return result;
}
单一检查成语
private volatile FieldType field;
FieldType getField() {
FieldType result = field;
if (result == null) {
field = result = computeFieldValue();
}
return result;
}
我们在第一种情况下使用锁定,据我所知,为了compute FieldValue()
原子地执行。但为什么我们在第二种情况下省略它呢?因为现在一些外来线程可能会破坏参与计算的某些值。我错过了什么?
答案 0 :(得分:4)
双重检查锁定的关键是确保computeFieldValue
仅被调用一次,而字段只被调用一次。
有些情况下,可以多次调用此方法,使双重检查锁定过度杀伤。这些是满足的一些条件:
computeFieldValue
应该是纯函数,始终返回相同的值;