基于volatile的解决方案
public class SafeDoubleCheckedLocking { // 1 |
双重检查锁锁定了instance = new Instance();
创建了一个对象,这一行代码可以分解为下面三行伪代码:
memory = allocate(); // 1. 分配对象的内存空间 |
上述的伪代码中,2和3之间因为有volatile的修饰,不会发生重排序了,就能保证拿到的对象是初始化之后的。
因为
new Instance()
是一个JVM指令码,对应的是new指令,volatile能够保证单个JVM指令的原子性,所以此处new Instance()
相当于是volatile写,会在new Instance()
前加上StoreStore屏障,后加StoreLoad屏障,其余线程就必须在StoreLoad屏障之后进行读取。实质上,new对象的三个步骤,依然可以重新排序,真正的控制是使用的外层的内存屏障。