java中静态字段的双重检查锁定

问题描述

我正在尝试使用 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 都没有关系,前提是:

  1. 被初始化的字段是 volatile 和,
  2. 执行 DCL 初始化的代码对任何给定字段使用相同的互斥对象。

前者显然是正确的。后者是正确的,因为对 getField4() 的所有调用都锁定同一个 Class 对象。

1 - 在 Java 5 之前,volatile 的指定语义不足以保证代码是线程安全的。
2 - 线程安全但丑陋。最好避免使用 DCL 习语并使用其他替代方法之一。


我不能使方法成为静态方法...

我不明白为什么不。它是 private,因此您不应受限于它是静态方法还是实例方法。它应该只影响当前类。

但如上所述,它对习语没有任何影响。