volatile关键字不但可以防止指令重排,也可以保证线程访问的变量值是主内存中的最新值

完整版 双重校验单例模式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class Singleton {
private Singleton() {} //私有构造函数
private volatile static Singleton instance = null; //单例对象
//静态工厂方法
public static Singleton getInstance() {
if (instance == null) { //双重检测机制
synchronized (this){ //同步锁
if (instance == null) { //双重检测机制
instance = new Singleton();
}
}
}
return instance;
}
}

期望的执行顺序:

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

如果不加volatile 关键字,那么,就会发生指令重排序.出现下面的情况.

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

volatile关键字不但可以防止指令重排,也可以保证线程访问的变量值是主内存中的最新值