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

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 张聪珉 中级黑马   /  2013-8-10 00:49  /  1322 人查看  /  8 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

本帖最后由 张聪珉 于 2013-8-10 00:53 编辑
  1. class  Single
  2. {       
  3.         private single(){}
  4.         private static Single s =null;
  5.         public void single getInstance()
  6.         {
  7.                 if(s==null)
  8.                 {
  9.                         synchronized(single.class)
  10.                         {
  11.                                 if(s==null)// 为什么还要再判断一次,我觉得这里可以不用再判断啊,我是这么想 的,因为如果s判断为空就创建了一个对象,这时候别的线程再来调用这个方法直接就在
  12.                                                         // 外部判断s不为空了,然后直接返回s。我所的对不对,求指导
  13.                
  14.                                         s =new single();
  15.                         }
  16.                 }
  17.                 return s
  18.        
  19.         }
  20.        
  21. }
复制代码

评分

参与人数 1技术分 +2 收起 理由
滔哥 + 2

查看全部评分

8 个回复

倒序浏览
  1. class  Single
  2. {        
  3.         private single(){}
  4.         private static Single s =null;
  5.         public void single getInstance()
  6.         {
  7.                 if(s==null)        //多线程中,如果有线程thread1在这里判断s==null,然后转到另一线程thread2,那么会出现两个线程都判断s==null,所以要在后面再判断一次
  8.                 {                          
  9.                         synchronized(single.class)
  10.                         {
  11.                                 if(s==null)// 为什么还要再判断一次,我觉得这里可以不用再判断啊,我是这么想 的,因为如果s判断为空就创建了一个对象,这时候别的线程再来调用这个方法直接就在
  12.                                                         // 外部判断s不为空了,然后直接返回s。我所的对不对,求指导
  13.                
  14.                                         s =new single();
  15.                         }
  16.                 }
  17.                 return s
  18.         
  19.         }
  20.         
  21. }
复制代码
回复 使用道具 举报
class  Single
{        
        private single(){}
        private static Single s =null;
        public void single getInstance()
        {
                if(s==null)
                {
                       //假如有两个线程同时访问,第一个null判断,它们都为空;所以两个线程都进来了
                       //
                      //     ------->A    此时A对象引用也为空,等B线程转出同步,A线程就可以进入同步,创建新的对象


                        synchronized(single.class)   
                        {
                      //    --------->B       B线程先行一步,并锁住程序,创建对象s后,又会打开锁,这时候A线程对象也是为空,进入同步,如果不再次判断,程序会重复创建对象!  
                            //    if(s==null)// 为什么还要再判断一次,我觉得这里可以不用再判断啊,我是这么想 的,因为如果s判断为空就创建了一个对象,这时候别的线程再来调用这个方法直接就在
                                                        // 外部判断s不为空了,然后直接返回s。我所的对不对,求指导         

                                        s =new single();
                        }
                }
                return s        
        }        
}

回复 使用道具 举报
问题的原因前面两位已经说了,这里我想补充一下的是这种情况出现的根本原因:
CPU处理进程(或线程)是以“时间片轮转”方式进行的。也就是说如果有多个进程,那么它每个进程只处理很小的一段时间,就会转去处理其他进程。
所以,如果有两个线程A、B,那么A在刚判断完第一个“if(s==null)”时,CPU突然去处理B线程了,这种可能是存在的。
回复 使用道具 举报
只要扯到多线程问题,那么肯定就会有效率问题。而双重判断s==null就省略了一部分程序去进入锁。例如有两个线程AB,几乎是同时访问这个方法。当AB线程访问到第一个s==null判断时,那时候内存中没有实例,随机的AB线程继续往下走,假如是A线程往下走,但是这时候B线程还没往下走(注意:这点必须注意。不然后面分析没意义)。读到了锁,然后B进不来。A此时已经new出实例。但是如果你此时不判断s==null,那么B可能也就会new出对象。这是s==null的意义所在。当然要解决这问题,synchronized直接加方法那就可以。但是为什么synchronized要加那儿。这就是效率问题了。因为当第三个线程C要访问时候,他根本不需要进入到锁。因为第一个s==null已经拦截了。所以效率大大提高直接synchronized。
回复 使用道具 举报
搞懂了,感谢各位的指导……:handshake
回复 使用道具 举报
各位回答的很详细,给力,新人学习啦,谢谢啊!!!!
回复 使用道具 举报
两种模式 懒汉模式  和饿汉模式。
回复 使用道具 举报
解释的很详细啊,感觉多线程这一块比较纠结,受教了
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马