【发布时间】:2018-01-10 22:53:57
【问题描述】:
我知道Java 的经典double-checked locking 习惯用法,它首先检查给定字段是否为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 上的同步可以细化为@ 987654329@?
示例
我有一个非常大的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;
}
【问题讨论】:
-
用于同步块的监视器不是恒定的 - 这看起来不正确。在
this(或private final Object lock - new Object();)上同步有什么问题? -
我宁愿避免锁定整个对象
this,这样即使在field的初始化期间也可以调用不影响field状态的方法。但是,我从没想过使用锁/互斥对象;这可能是我会接受的答案。 -
我想强调的是,在整个对象
this上进行同步不会影响“不影响field状态的方法”,即调用这些方法只会阻塞它们包含synchronized(this);见stackoverflow.com/questions/11981227/…
标签: java synchronization member weak-references double-checked-locking