volatile 的底层实现原理是内存屏障,Memory Barrier(Memory Fence)
对 volatile 变量的写指令后会加入写屏障,写屏障保证在该屏障之前,对共享变量的改动都存到主存中。
对 volatile 变量的读指令前会加入读屏障,读屏障(lfence)保证在该屏障之后,对共享变量的读取,加载的是主存中最新数据。
写屏障会确保指令重排序时,不会将写屏障之前的代码排在写屏障之后;
读屏障会确保指令重排序时,不会将读屏障之后的代码排在读屏障之前;
public final class Singleton {
private Singleton() { }
private static volatile Singleton INSTANCE = null;
public static Singleton getInstance() {
// 实例没创建,才会进入内部的 synchronized代码块
if (INSTANCE == null) {
synchronized (Singleton.class) { // t2
// 也许有其它线程已经创建实例,所以再判断一次
if (INSTANCE == null) { // t1
INSTANCE = new Singleton();
}
}
}
return INSTANCE;
}
}