双二单二博出五解

此方法将同步的内容移动到if内部只有第一次创建才会同步,提高了效率但是,该方法会受到指令重排序的影响

指令重排序指令重排序是为了优化指令提高程序运荇效率。指令重排序包括编译器重排序和运行时重排序JVM规范规定,指令重排序可以在不影响单线程程序执行结果前提下进行例如 instance = new Singleton() 可分解为如下伪代码:

但是经过指令重排序后会变成这样

//注意,此时对象还没有被初始化!

这样就会现问题线程A执行了instance = memory(),这一步对线程B是可見那么,线程B判断if(instance == null)时便会发现instance已经不为空了便会返回instance,但是由于instance只是指向了内存地址,并没有真正的初始化那么线程B将会返回一個未能完全初始化的instance。

于是修订版现,使用两个同步块加一个局部变量来试图解决此问题先用同步块初始化局部变量,完全初始化后賦值给instance以此保证instance是完全初始化的。

但是这种方法依然存在问题,java规定了同步块里的内容必须在对象锁释放之前执行完毕(也就是一个線程必须执行完才能让另一个线程执行)但并没有规定同步块之外的代码,必须在同步块执行完之后执行也就意味着,

 在运行过程中佷可能跑到内层同步块中这样,指令重排序的问题又再次现也就是说,sc指向内存地址后还没有初始化时就赋值给了instance导致外部线程直接得到没有完全初始化的instance。

在JDK1.5之后可以使用volatile变量禁止指令重排序,让DCL生效

}

我要回帖

更多关于 解出双入对 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信