gpt4 book ai didi

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

转载 作者:行者123 更新时间:2023-12-01 17:55:20 25 4
gpt4 key购买 nike

我知道经典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/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com