public class DoubleCheckedLocking{
private static Instance instance;
public static Instance getInstance(){
if(instance == null){//第一次检查
synchronized (DoubleCheckedLocking.class){//加锁
if(instance == null){//第二次检查
instance = new Instance();//注意:问题就出在这里。
}
}
}
return instance;
}

}

对上面的问题进行分析(instance = new Instance()):
instance = new Instance() 创建对象,这一行代码可以分解为如下的3行代码:
memory = allocate(); //1.分配对象的内存空间
ctorInstance(memory); //2.初始化对象
instance = memory; //3.设置instance 指向刚分配的内存地址

因为在一些JIT编译器上,2,3步骤可能会被重排序如下:
memory = allocate(); //1.分配对象的内存空间
instance = memory; //3.设置instance 指向刚分配的内存地址
//注意:此时对象还没有被初始化
ctorInstance(memory); //2.初始化对象

在知晓了问题发生的根源后,我们可以想出两个办法来解决这个问题:
1.不允许2和3重排序;
2.允许2,3重排序,但不允许其他线程“看到”这个重排序;


最终的解决方案:(基于volatile)
public class SafeDoubleCheckedLocking(){
private volatile static Instance instance;
public static Instance getInstance(){
if(instance == null){
synchornized(SafeDoubleCheckedLocking.class){
if(instance == null){
instance = new Instance();
}
}
}
return instance;
}

}

 

posted on 2017-02-09 15:07  coder_ornot  阅读(139)  评论(0编辑  收藏  举报