我正在研究 Effective Java(第二版)的第 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
鉴于初始化发生在同步块中,为什么需要 volatile 修饰符?这本书提供了以下支持文本:“因为如果字段已经初始化,则没有锁定,因此将字段声明为 volatile至关重要”。因此,是不是一旦字段被初始化,field
在没有其他同步的情况下,volatile 是多线程一致视图的唯一保证?如果是这样,为什么不同步 getField() 或者上面的代码提供了更好的性能?文本建议使用不需要的局部变量 ,
result
以“确保field
在已初始化的常见情况下仅读取一次”,从而提高性能。如果result
被删除,在已经初始化的常见情况下如何field
多次读取?