youyichannel

志于道,据于德,依于仁,游于艺!

0%

Volatile全解读-06

基于volatile的解决方案

public class SafeDoubleCheckedLocking { // 1
private volatile static Instance instance; // 2

public static Instance getInstance() { // 3
if(instance == null) { // 4 第一次检查
synchronized(SafeDoubleCheckedLocking.class) { // 5 加锁
if(instance == null) { // 6 第二次加锁
instance = new Instance(); // 7 无问题存在了
}
} // 8
} // 9
return instance; // 10
} // 11
}

双重检查锁锁定了instance = new Instance();创建了一个对象,这一行代码可以分解为下面三行伪代码:

memory = allocate(); // 1. 分配对象的内存空间
ctorInstance(memory); // 2. 初始化对象
instance = memory; // 3. 设置instance指向刚分配的内存地址

上述的伪代码中,2和3之间因为有volatile的修饰,不会发生重排序了,就能保证拿到的对象是初始化之后的。

因为new Instance()是一个JVM指令码,对应的是new指令,volatile能够保证单个JVM指令的原子性,所以此处new Instance()相当于是volatile写,会在new Instance()前加上StoreStore屏障,后加StoreLoad屏障,其余线程就必须在StoreLoad屏障之后进行读取。实质上,new对象的三个步骤,依然可以重新排序,真正的控制是使用的外层的内存屏障。

视频地址 强推 河北王校长