java - 非空类成员字段的双重检查锁定

标签 java synchronization member weak-references double-checked-locking

我知道经典double-checked locking成语Java ,它首先检查给定字段是否为 null如果是这样,则获取具有以下字段的类的锁:

// Double-check idiom for lazy initialization of instance fields
// See Pascal Thivent's original answer <https://stackoverflow.com/a/3580658/1391325>
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 的情况下永远不会为空(而是引用“null object”值,该值被延迟替换为“非空对象”),可以同步this细化为synchronized(field)

示例

我有一个非常大的 HugeObject然而,它可以很容易地重新创建。我希望垃圾收集器能够在内存开始耗尽的情况下丢弃此实例,因此我用 Reference<HugeObject> 保留它。 ,并将其初始化为Reference<HugeObject> field = new SoftReference<>(null) 。我宁愿避免锁定整个对象 this这样使用的方法就不会影响 field 的状态即使在 field 初始化期间也可以调用。那么是否可以简单地获取这个初始“空对象”或已经实例化的“非空对象”上的锁,或者这可能会导致微妙的结果,不需要的并发影响?请参阅下面的代码:

private volatile Reference<HugeObject> field = new SoftReference<>(null);

HugeObject getField() {
    HugeObject result = field.get();
    if (result == null) {
        synchronized(field) {
            result = field.get();
            if (result == null) {
                result = computeFieldValue();
                field = new SoftReference<>(result);
            }
        }
    }
    return result;
}

最佳答案

如果您不想在上进行同步,则可以使用其他引用。但该引用需要保持不变。在您的示例中,您锁定了被重新分配的 field - 因此,如果两个线程具有不同的 field 值,则它们可以同时执行您的方法。

一个标准解决方案是使用专用锁:

private final Object lock = new Object();

//...

synchronized(lock) { ... }

关于java - 非空类成员字段的双重检查锁定,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45482437/

相关文章:

java - 如何在Spring RestTemplate中实现批处理

java - 如何从 java 执行 shell 脚本,它会重启 tomcat 并继续运行

java - 如何从kafka主题中按键获取消息

android - 在 Android 中,如何同步录音和同步播放?

java - 是否同步保留锁

java - 成员变量在声明时未能初始化

c++ - 通过成员数组循环给出错误的值

class - 具有成员 std::mutex(或其他不可复制对象)的类的复制或移动构造函数?

java - 在受约束的多对多数据集中有效地查找重复项?

java - 锁定多个对象