【问题标题】:Double checked locking for static fields in javajava中静态字段的双重检查锁定
【发布时间】:2021-01-20 22:53:30
【问题描述】:

我正在尝试使用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 thread-safety static-analysis double-checked-locking


    【解决方案1】:

    假设您使用的是 Java 5 或更高版本1,以上代码是线程安全的2

    方法或字段是否为static 无关紧要,前提是:

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

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

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


    我无法将方法设为静态方法...

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

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

    【讨论】:

    • 同意——它很丑,但它在技术上是线程安全的(除非类型是 long——我认为在这种情况下,它不能保证是线程安全的)。如果计算方法将始终解析为相同的值并且在性能方面相对微不足道,您也可以放弃同步并接受两个线程可能同时将字段初始化为其计算值的竞争条件。
    • 谢谢。我的方法是公开的而不是私有的,我错误地发布为私有。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-04-04
    • 2018-01-10
    • 2016-04-03
    • 2011-08-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多