java 单例模式中双重检查锁定 volatile 的作用?为什么样在Java里面string s= new String("John"); s = new String(&quo

时间:2017-12-21 08:00:01   浏览:次   点击:次   作者:   来源:   立即下载

volatile 是保证了可见性还是有序性?

有序性:是因为 instance = new Singleton(); 不是原子操作。编译器存在指令重排,从而存在线程① 创建实例后(初始化未完成),线程② 判断对象不为空,但实际对象扔为空,造成错误。

可见性:是因为线程① 创建实例后还只存在自己线程的工作内存,未更新到主存。线程 ② 判断对象为空,创建实例,从而存在多实例错误。

题主自己都说了,可见性和有序性两者都有。

既然涉及到这两者,自然会想到happens-before规则。目前大部分对这类问题的分析,都是比较简单粗暴的从可见性、原子性、有序性等角度来说。题主可以试试利用happens-before规则来分析,这也很有意思。

*************** 以下更新 ****************

之前回答的时候没细想,看了 @陈大白 的答案才想起来,这里的instance变量本身不存在可见性问题。但是,instance对象内部的字段,如果不是final,那么存在可见性问题。

public class LazySingleton { private int someField; private static LazySingleton instance; private LazySingleton() { this.someField = ①; // (①) } public static LazySingleton getInstance() { if (instance == null) { // (②) synchronized(LazySingleton.class) { // (③) if (instance == null) { // (④) instance = new LazySingleton(); // (⑤) } } } return instance; // (⑥) } public int getSomeField() { return this.someField; // (⑦) }}

简而言之,当你通过上面的getInstance方法拿到①个LazySingleton实例以后,去调用实例的getSomeField方法,是没法保证能看到①这个值的。

可以证明,(⑦) happens before (①)是不成立的。

先上图

题目中s是有用对象,可达。不属于内存泄露。

内存泄露的例子:

Vector v = new Vector(①⓪);

for (int i = ①; i

收起

相关推荐

相关应用

平均评分 0人
  • 5星
  • 4星
  • 3星
  • 2星
  • 1星
用户评分:
发表评论

评论

  • 暂无评论信息