其中一篇文章提到了“双重检查锁定”(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. 实例非空,但尚未设置field1和field2! 此线程看到的是field1和field2的无效值!
由于新实例(new MyBrokenFactory())的创建是从同步块中完成的,因此在整个初始化完成之前(private MyBrokenFactory()完全执行)是否会释放锁定? 参考资料 - https://www.javamex.com/tutorials/double_checked_locking.shtml 请解释。
instance
的非空值,则您无法可靠地访问它,因为该线程不进入同步块,因此对象未同步。 - Tootsie