A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

//单例设计模式中懒汉式在被多线程访问时,同步代码块中为什么要双重if语句判断?总想不清楚,求大神提点!
  1. class Single
  2.             {
  3.                     private static Single s = null;
  4.                     private Single(){}
  5.                     public static synchronized Single getInstance()
  6.                     {                       
  7.                             //老想不明白这里为什么要双重否定??
  8.                             if(s == null)
  9.                             {
  10.                                     synchronized(Single.class)
  11.                                     {
  12.                                             if(s == null)
  13.                                                     s = new Single();
  14.                                     }
  15.                             }
  16.                             return s;
  17.                     }
  18.             }
复制代码

评分

参与人数 1技术分 +1 收起 理由
枫儿 + 1 神马都是浮云

查看全部评分

6 个回复

倒序浏览
楼主的代码貌似写错了吧?方法上应该没有synchronized这个关键字,因为里面有了。现在分析假如没有第一个if(n=null),那么就和在方法上加synchronized没有区别。在多线程进入的时候,考虑最坏的打算。两个线程都进入,而只有一个线程可以进入synchronized(Single.class),当这个线程出来时,另一个线程进入,但是synchronized里面还有一个判断if(n==null),此时n已经new出对象了。所以直接return n;所以不加第一个if(n==null)是可以的。
但是为什么要加上呢?因为每一个线程进来的时候都需要判断synchronized(Single.class)这个锁。很消耗时间。所以为了优化,而在synchronized(Single.class)前面加上判断if(n==null),此时如果单例设计已经完成,那么别的线程执行这个的话就会直接 return n; 而不用再进行判断synchronized(Single.class).

不知楼主明白了吗?

评分

参与人数 1技术分 +1 收起 理由
枫儿 + 1 赞一个!

查看全部评分

回复 使用道具 举报
外面if是判断s是否为空的,它的作用是减少了判断锁的次数,里面的if是当s为空时建立对象用的
回复 使用道具 举报
本帖最后由 刘一博 于 2014-4-1 20:49 编辑

首先说里面的if()条件必须要有,判断是否已经初始化对象了
之所以外面加完了,里面还要加判断是为了防止,线程高并发都通过了外层的if条件判断
加synchronized是为了让多线程抢占锁,线程安全
在外层加if可以省去,但是多线程抢占锁会耗费资源,加上优化了代码,防止不必要的资源损失

评分

参与人数 1技术分 +1 收起 理由
枫儿 + 1 赞一个!

查看全部评分

回复 使用道具 举报
本帖最后由 闲人 于 2014-4-1 20:55 编辑

假如没有外面的if,那么程序运行时,
判定是否有锁
      |--有锁,则暂停
      |--没锁,判断是否为空
                   |---当空时,开始运行
                   |---当不空时,暂停

假如外面有if
程序会直接判定是否为空
           |--当空时,运行以上内容
           |--当不空时,暂停


双层if的好处是,可以节省判断锁的次数,降低内存的运行,让程序更快

评分

参与人数 1技术分 +1 收起 理由
枫儿 + 1 赞一个!

查看全部评分

回复 使用道具 举报
清风有意 发表于 2014-4-1 18:41
楼主的代码貌似写错了吧?方法上应该没有synchronized这个关键字,因为里面有了。现在分析假如没有第一个if ...

是多了个synchronized。   多谢,思路更清晰了。
回复 使用道具 举报
楼主可以网上查查懒汉式双重判断的原因,有详细解答的。
http://plplum.blog.163.com/blog/static/31032400201241534840891/

简单的说,第一个if目的是提高效率的,第二个if的目的是出于安全考虑,确保只创建一个实例
1.第一个if的作用
假如有两个线程A,B同时进入函数(第6行),A的时间片到了,A在时间片内执行完了函数,那堆中已经有了一个实例,这时B的时间片到了,B判断第一个if,(s!=null),所以不用进锁,直接返回s,提高了效率,如果没有第一个if,那么B也会进锁,降低效率
2.第二个if的作用
假如有两个线程C,D同时进入第一个if(第9行),C的时间片到了,进锁(D不能进了,要等待),创建了一个实例,C创建完实例释放锁,D能进锁,这时,(s!=null),于是返回s,确保堆中只有一个实例

评分

参与人数 1技术分 +1 收起 理由
枫儿 + 1 赞一个!

查看全部评分

回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马