JVM指令重排导致Singleton双重锁定出错

来源:互联网 发布:rgb颜色渐变算法 c 编辑:程序博客网 时间:2024/05/20 06:24

指令重排导致单例模式失效

我们都知道一个经典的懒加载方式的单例模式:

public class Singleton {

private static Singleton instance = null;

private Singleton() { }

public static Singleton getInstance() {

if(instance == null) {

synchronzied(Singleton.class) {

if(instance == null) {

instance = new Singleton();

}

}

}

return instance;

}

}

看似简单的一段赋值语句:instance = new Singleton();,其实JVM内部已经转换为多条指令:

memory = allocate(); //1:分配对象的内存空间

ctorInstance(memory); //2:初始化对象

instance = memory; //3:设置instance指向刚分配的内存地址

但是经过重排序后如下:

memory = allocate(); //1:分配对象的内存空间

instance = memory; //3:设置instance指向刚分配的内存地址,此时对象还没被初始化

ctorInstance(memory); //2:初始化对象

可以看到指令重排之后,instance指向分配好的内存放在了前面,而这段内存的初始化被排在了后面,在线程A初始化完成这段内存之前,线程B虽然进不去同步代码块,但是在同步代码块之前的判断就会发现instance不为空,此时线程B获得instance对象进行使用就可能发生错误。


修改:

public class Singleton {private static  volatile Singleton instance = null;private Singleton() { }public static Singleton getInstance() {if(instance == null) {synchronzied(Singleton.class) {if(instance == null) {instance = new Singleton();}}}return instance;}}


0 0
原创粉丝点击