单例模式代码:
public class SingletonDemo {
private volatile static SingletonDemo instance = null;
private SingletonDemo(){}
public static SingletonDemo getInstance(){
// DCL(double check lock)双端检测
if(instance == null){
synchronized (SingletonDemo.class){
if(instance == null){
instance = new SingletonDemo();
}
}
}
return instance;
}
}
为什么instance需要用volatile修饰那?
instance = new SingletonDemo();可以分为下面三步完成(伪代码)
1.memory = allocate(); //1.分配对象内存空间
2.instance(memory); //2.初始化对象
3.instance = memory;//3.设置instance指向刚分配的内存地址,此时instance!=null;
步骤2和3之间不存在**数据依赖关系**,在多线程环境很有可能发生指令的重排,执行顺序变为132,即
1.memory = allocate(); //1.分配对象内存空间
3.instance = memory;//3.设置instance指向刚分配的内存地址,此时instance!=null,但是对象还没有初始化完成!
2.instance(memory); //2.初始化对象
即当一条线程访问instance不为null时,由于instance实力未必初始化完成,也就造成了线程安全问题。
所以instance需要volatile修饰,即在instance初始化完成前后添加了栅栏(内存屏障),禁止了指令的重排。