双锁检测不安全问题的分析
package single;
/**
* @author: Zekun Fu
* @date: 2022/5/23 9:59
* @Description: 双锁检测,如果不加volatile线程不安全。
* 因为会访问到未初始化的对象
*/
public class Doubl_Lock_Check {
private static Doubl_Lock_Check instance; // 线程不安全
private volatile static Doubl_Lock_Check instance2; // 线程安全
private Doubl_Lock_Check(){} // 私有构造器
public static Doubl_Lock_Check getInstance() {
if (instance == null) {
synchronized (Doubl_Lock_Check.class) {
instance = new Doubl_Lock_Check();
}
}
return instance;
}
public static Doubl_Lock_Check getInstance2() {
if (instance2 == null) {
synchronized (Doubl_Lock_Check.class) {
instance2 = new Doubl_Lock_Check();
}
}
return instance2;
}
public static void main(String[] args) {
}
}
下面是创建对象的字节码指令:
下面是另一个线程获取对象的执行代码
如果putstatic指令,经过指令重排,放在了dup之前,那么getstatic指令就会获得没有调用初始化方法的对象,就会导致程序出问题。
也就是说,如果没有经过初始化的对象,被另一个线程所引用。那么会导致空指针或者访问未初始化的变量异常。
加上了volatile防止指令重排,上面的问题就不会出现。