11
回答
单例模式双重判断的疑惑
【腾讯云】学生服务器套餐10元/月 >>>   
在单例模式中,有一种是需要双重判断的,外层的判断我能理解,为什么进入 synchronized 之后还需要再判断一次?求解惑.
举报
小小丁灬
发帖于2年前 11回/557阅
共有11个答案 最后回答: 2年前

private static Object instance=null;
private static final byte[] b = new byte[0];
public static Object getInstance() {
    if(instance == null) {//线程1,2到达这里
        synchronized(b) {//线程1到这里开始继续往下执行,线程2等待
            if(instance == null) {//线程1到这里发现instance为空,继续执行if代码块,
             //执行完成后退出同步区域,然后线程2进入同步代码块,如果在这里不再加一次判断,
             //就会造成instance再次实例化,由于增加了判断,
             //线程2到这里发现instance已被实例化于是就跳过了if代码块
               instance = new Object();
            }
        }
    }
 }



以上描述,能让你明白没


个人觉得, 下面这种方式, 如果不双重判断, 会照成多次实例化. 如 2个线程都通过了外层A的判断, 线程1先进入A得到锁, 线程2在进入就会等待线程1完成, 如果没有双重判断, 就会执行2次C. 这时候加个B判断, 就可以避免了.

private static String instance = null;
	public void sendMsgAndSaveInfo1(String value) {
		// A
		if(null == instance) {
			// B
			synchronized (this) {
				// C
				if(null == instance) {
					instance = new String(value);// 新的String
				}
			}
		}
	}



本意是为了解决多线程情况下使用同步代码块引起的性能问题,但是jvm的类加载机制会导致获得未初始化的对象的问题。

引用来自“Shazi199”的评论

本意是为了解决多线程情况下使用同步代码块引起的性能问题,但是jvm的类加载机制会导致获得未初始化的对象的问题。
正解

引用来自“Shazi199”的评论

本意是为了解决多线程情况下使用同步代码块引起的性能问题,但是jvm的类加载机制会导致获得未初始化的对象的问题。

引用来自“wangaowell”的评论

正解
不懂楼上两位说的啥意思,跟类加载机制有啥关系...正确不是1楼讲的么?
--- 共有 1 条评论 ---
wangaowell是的。 2年前 回复
volatile修饰的话就可以确保instance对应的指令不会重排序,否则jvm的类加载机制会导致获得未初始化的对象的问题。
--- 共有 1 条评论 ---
Ambitor了解了下,感觉是要加上volatile,但是说法有点不对 跟类加载器没啥关系吧。 2年前 回复
顶部