单例双重校验为什么还要加 volatile
Java 面试 About 956 words单例代码
双重校验 + volatile
public class Singleton {
//防止在new对象时指令重排序
private static volatile Singleton instance;
private Singleton() {
}
public static Singleton getInstance() {
if (instance == null) {
synchronized (Singleton.class) {
if (instance == null) {
instance = new Singleton();
}
}
}
return instance;
}
}
原因
Java
层面实例化对象时instance = new Singleton();
底层C
代码实际分为3
个步骤:(字节码层面也可以看到分为了三步)
memory = alloct(); // 1. 分配对象的内存空间
ctorinstance(memory); // 2. 初始化对象
instace = memory; // 3. 设置 instace 指向刚分配的内存地址
如果不加volatile
关键字,可能发生指令重排序(虽然概率很低),导致初始化对象这一步在指向内存地址之后。若此时其他线程调用getInstance()
方法,实例已经不为null
了,则第一个 if 就判断了不为 null 直接返回,但此时仅仅是指向了一个分配好的内存地址,并没有真正完成实例化,导致空指针。
memory = alloct(); // 1. 分配对象的内存空间
instace = memory; // 3. 设置 instace 指向刚分配的内存地址
// 这一步此对象还没有被初始化,若其他线程来调用 getInstance(),就有问题了
ctorinstance(memory); // 2. 初始化对象
Views: 1,342 · Posted: 2022-05-18
————        END        ————
Give me a Star, Thanks:)
https://github.com/fendoudebb/LiteNote扫描下方二维码关注公众号和小程序↓↓↓
Loading...