问题描述
我正在尝试使用 Bloch's effective java recommendation 修复双重检查锁定。但是我的代码中的一个小变化是字段类型是静态的,而创建字段类型的方法是实例方法。 以下用于创建静态字段的变体是否有效?
private static volatile FieldType field4;
// NOTE: The code for this method in the first printing had a serIoUs error (see errata for details)!
public FieldType getField4() {
FieldType result = field4;
if (result != null) // First check (no locking)
return result;
synchronized(Initialization.class) {
if (field4 == null) // Second check (with locking)
field4 = computeFieldValue();
return field4;
}
}
我无法将方法设为静态方法 // 静态字段的延迟初始化持有者类习语 - 第 334 页。
解决方法
假设您使用的是 Java 5 或更高版本1,以上代码是线程安全的2。
方法或字段是否为 static
都没有关系,前提是:
- 被初始化的字段是
volatile
和, - 执行 DCL 初始化的代码对任何给定字段使用相同的互斥对象。
前者显然是正确的。后者是正确的,因为对 getField4()
的所有调用都锁定同一个 Class
对象。
1 - 在 Java 5 之前,volatile
的指定语义不足以保证代码是线程安全的。
2 - 线程安全但丑陋。最好避免使用 DCL 习语并使用其他替代方法之一。
我不能使方法成为静态方法...
我不明白为什么不。它是 private
,因此您不应受限于它是静态方法还是实例方法。它应该只影响当前类。
但如上所述,它对习语没有任何影响。