我无法理解“Effective Java”第 71 条中有关双重检查惯用法和用于实例字段延迟初始化的单检查惯用法的代码:
双重检查习语
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;
}
据我了解,我们在第一种情况下使用锁定,以便以原子方式执行计算 FieldValue()
。但为什么我们在第二种情况下省略它呢?因为现在某些外来线程可能会破坏参与计算的某些值。我错过了什么?
最佳答案
双重检查锁定的要点在于,它确保computeFieldValue仅被调用一次,并且字段仅被写入一次。
在某些情况下,多次调用此方法是可以接受的,这使得双重检查锁定变得矫枉过正。以下是需要满足的一些条件:
computeFieldValue
应该是一个纯函数,始终返回相同的值;- 被多次调用的风险程度是可以接受的(发生这种情况的可能性乘以它的性能影响)。
关于java - 单次和双重检查延迟初始化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28048689/