黑马程序员技术交流社区

标题: 关于单例设计模式中懒汉式被多线程访问的问题。 [打印本页]

作者: ╰青青子佩ˊゝ    时间: 2014-4-1 18:24
标题: 关于单例设计模式中懒汉式被多线程访问的问题。
//单例设计模式中懒汉式在被多线程访问时,同步代码块中为什么要双重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.             }
复制代码

作者: 清风有意    时间: 2014-4-1 18:41
楼主的代码貌似写错了吧?方法上应该没有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).

不知楼主明白了吗?
作者: 杨殿生    时间: 2014-4-1 19:07
外面if是判断s是否为空的,它的作用是减少了判断锁的次数,里面的if是当s为空时建立对象用的
作者: 刘一博    时间: 2014-4-1 20:47
本帖最后由 刘一博 于 2014-4-1 20:49 编辑

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


作者: 闲人    时间: 2014-4-1 20:51
本帖最后由 闲人 于 2014-4-1 20:55 编辑

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

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


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

作者: ╰青青子佩ˊゝ    时间: 2014-4-1 21:22
清风有意 发表于 2014-4-1 18:41
楼主的代码貌似写错了吧?方法上应该没有synchronized这个关键字,因为里面有了。现在分析假如没有第一个if ...

是多了个synchronized。   多谢,思路更清晰了。
作者: 帅哥哥    时间: 2014-4-1 21:41
楼主可以网上查查懒汉式双重判断的原因,有详细解答的。
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,确保堆中只有一个实例




欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2