【发布时间】:2019-04-04 06:13:28
【问题描述】:
其中一篇文章提到了"Double Check Locking" 的问题。请看下面的例子
public class MyBrokenFactory {
private static MyBrokenFactory instance;
private int field1, field2 ...
public static MyBrokenFactory getFactory() {
// This is incorrect: don't do it!
if (instance == null) {
synchronized (MyBrokenFactory.class) {
if (instance == null)
instance = new MyBrokenFactory();
}
}
return instance;
}
private MyBrokenFactory() {
field1 = ...
field2 = ...
}
}
原因:-(请注意编号的执行顺序)
线程 1:“首先进入”并开始创建实例。 1. 实例是否为空?是的。 2.同步上课。 3. 例如分配内存。 4. 指向保存到实例中的内存的指针。 [[线程 2]] 7. field1 和 field2 的值被写入 分配给对象的内存。 ..................... 线程 2:在线程 1 写入对象引用时进入 到内存,但在它写完所有字段之前。 5. 实例是否为空?不。 6.instance不为null,但是field1和field2还没有设置! 此线程看到 field1 和 field2 的无效值!问题:
由于新实例的创建(new MyBrokenFactory())是从同步块中完成的,在整个初始化完成之前会不会释放锁(私有的MyBrokenFactory()完全执行)?
参考 - https://www.javamex.com/tutorials/double_checked_locking.shtml
请解释一下。
【问题讨论】:
-
另外简短地回答一下您的规范“将在整个初始化完成之前释放锁”答案是:不。但由于第二个线程甚至从未尝试获取锁,这在这里对您没有帮助。
-
我想解决办法是声明
instancevolatile -
我知道 volatile 会修复它。伙计们,我不是在问什么是修复我的问题是关于线程锁定的基本问题。由于新实例的创建(new MyBrokenFactory())是从同步块中完成的,在整个初始化完成之前会释放锁吗(私有的MyBrokenFactory()完全执行)?
-
@Sunny 问题是不能定义“整个初始化完成”。是的,对于创建它的线程,答案是肯定的。但是其他线程可能会观察到部分构造的对象,因为缺少同步
-
更准确地说,如果第二个线程观察到
instance的非空值,则您无法可靠地访问它,因为该线程没有进入同步块,因此对象未同步跨度>
标签: java multithreading synchronization thread-safety