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

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 李东梁 中级黑马   /  2014-4-14 19:48  /  1258 人查看  /  5 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

  1. class Single
  2. {
  3.         private static Single s = null;
  4.         private Single(){}
  5.         public static  Single getInstance()
  6.         {
  7.                 if(s==null)<font color="Red">//第一次判断是否为空</font>
  8.                 {
  9.                         synchronized(Single.class)
  10.                         {
  11.                                 if(s==null)<font color="Red">//第二次判断是否为空</font>
  12.                                 {
  13.                                         s = new Single();
  14.                                 }
  15.                         }
  16.                 }
  17.                 return s;
  18.         }
  19. }
复制代码

两次判断的目的就是为了提高效率,第一次已经判断过了,第二次是不是不用判断了,能进来的不都是非空的吗,加了第二次判断,不又降低效率了吗?

评分

参与人数 1技术分 +1 收起 理由
ily521125 + 1

查看全部评分

5 个回复

倒序浏览
不是这样的,当一个线程判断为null之后,如果被CPU切走了,另一个线程进来了,然后进入到同步代码块中,new一个对象出去了,然后刚刚躺下的线程回来之后就不会再判断前面的if了,就会进入到同步代码块中,如果里面没有if的话,就又new了一个对象,就不是单例了

评分

参与人数 1黑马币 +12 收起 理由
李东梁 + 12 很给力!

查看全部评分

回复 使用道具 举报
额,这样做恰好提高了效率,楼主可以这样想,假如这个单例对象已经存在,因为有第一个if,线程直接就能取走单例对象,而没第一个if,线程还要先获得锁,再判断s是否为空,然后才能取走单例对象,这样效率反而下降了
回复 使用道具 举报
三个阶段 1 判断是否为空 2 判断里面是否有人 3 判断是否为空
如果没有第三个阶段
第一个线程进入,1判断,是空,2判断,没人,进去以后,睡了。
第二个线程进入,1判断,是空,2判断,有人,在2号位置上等。
第一个线程醒了,建立对象,拍拍屁股走了。里面不是空了。
第二个线程,2判断,没人,进去以后又做了S=new Single();这个动作。如果有第三个判断的话,非空,就不会有创建动作了。
所以第三个是有用的,不能少。
回复 使用道具 举报
假如现在有2个线程A和B,当A线程执行到了同步块时被挂起,执行权被B夺走了,B线程执行到了第一个if判断的时候,这时B被挂起,执行权被A夺走,A线程在同步块中继续执行创建了对象,释放锁后,被B夺走执行权,B线程就进入了同步块,遇到了第二次if判断,发现已经有对象了,就不再执行创建对象的语句。若是还有第3条线程进来,会先执行第一个if,发现有对象了就不会再继续执行以下代码。
总结:第一条线程会执行完所有代码,第二条线程执行到第二个if就结束,之后的线程执行到第一个if判断就结束

评分

参与人数 1技术分 +1 收起 理由
何伟超 + 1

查看全部评分

回复 使用道具 举报
月光海 发表于 2014-4-14 20:01
不是这样的,当一个线程判断为null之后,如果被CPU切走了,另一个线程进来了,然后进入到同步代码块中,new ...

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