volatile
从单例模式引出
单例模式一文中,DCL实现单例使用了关键了volatile:
class Singleton5 {
private Singleton5() {
System.out.println("private Singleton3");
}
private static volatile Singleton5 INSTANCE = null;
public static Singleton5 getInstance() {
if (INSTANCE == null) {
synchronized (Singleton5.class) {
if (INSTANCE == null) {
INSTANCE = new Singleton5(); // *
}
}
}
return INSTANCE;
}
}
*处的代码反编译后的字节码指令为:
1: new // 给Singleton5这个对象分配空间
2: invokespecial // Method "<init>":()V 执行构造函数
3: putstatic // 将内存空间的地址赋值给对应的引用,也就是这里的INSTANCE
由于2和3这两个指令并没有依赖关系,所以CPU在执行的时候可能会发生指令重排序,即以这种顺序执行:
1: new // 给Singleton5这个对象分配空间
3: putstatic // 将内存空间的地址赋值给对应的引用,也就是这里的INSTANCE
2: invokespecial // Method "<init>":()V 执行构造函数
那么假设现在有两个线程执行这段代码,并且按照顺序执行:
线程1 线程2
new 分配空间
INSTANCE = 对象
if (INSTANCE == null)
return INSTANCE
Singleton5() 初始化
这样线程2拿到的对象就是没有初始化过对象,可能会出现问题。
说明
===================================
仅作为校招时的《个人笔记》,详细内容请看【参考】部分
===================================
参考
- B站,黑马满老师
- 《深入理解Java虚拟机》第3版

浙公网安备 33010602011771号