黑马程序员技术交流社区

标题: 懒汉式单例设计问题 [打印本页]

作者: 杨毅    时间: 2012-2-15 20:24
标题: 懒汉式单例设计问题
本帖最后由 杨毅 于 2012-2-15 23:21 编辑

class Single
{
        private static Single s =null;
        private Single(){}
       
        public static Single getInstance()
        {
                if(s==null)
                {
                        synchronized(Single.class)
                        {
                                if(s==null)
                                s = new Single();                       
                        }
                }
                return s ;
        }
}


本人新手,刚开始学,看到基础视频里面讲解的懒汉式单例模式时,不是很明白为什么在synchronized 里还要判断一次 if(s==null) ,不是已经判断过了吗?个人觉得没什么必要,去掉没区别啊?可以去掉么? 求解释 .
作者: 黄锦成    时间: 2012-2-15 20:42
可以写成这样:
public static Single getInstance()
         {
                         synchronized(Single.class)
                         {
                                 if(s==null)
                                 s = new Single();                        
                        }
                 return s ;
         }
,但是只要有一个创建出一个对象后,其他线程执行到这个方法,都会逐个去得到锁,进入if判断,这样会性能会降低。我们在锁的外面再加一个if(s==null),这样,只要s有了指向,其他线程执行这个方法,那么第一个if就不能进去,从而减少了判断锁的次数,性能得到了提高。

还有,同步代码块里的if不能去掉。如果去掉了,当两个线程执行到synchronized处时,线程A得到了锁,线程B在等待,当线程A创建了对象后,释放了锁,线程B将会得到锁,又会创建对象。这样就不能保证单例了。

建议使用两个if,中间夹着synchronized这种写法
作者: 魏腾飞    时间: 2012-2-15 20:58
public static Single getInstance()
        {
                if(s==null)
                {
                        synchronized(Single.class)
                        {
                                if(s==null)
                                s = new Single();                        
                        }
                }
                return s ;
        }
我认为是这么理解:首先N多线程进来访问getInstance(),
判断s是否存在根据优先级访问同步代码块接着判断执行创建新对象。
但是如果执行完后,对象存在了。接着如果还有N条再次进入getInstance()
根据第一个if就不用去访问内部代码。节省时间。
作者: 杨毅    时间: 2012-2-15 21:07
mnisummer 发表于 2012-2-15 20:42
可以写成这样:
public static Single getInstance()
         {

了解了 ,谢谢
作者: 李杨    时间: 2012-2-15 22:04
本帖最后由 李杨 于 2012-2-15 22:09 编辑

同学你好:
          首先你需要明白synchronized的作用,意思是当线程得到了cpu分配的随机时间片后并获得了锁,那么这个线程就可以执行同步代码块中的代码,没有得到时间片的线程只能等待cpu分配.



首先说明:线程拥有了执行权其实是得到cpu为该线程分配了随机时间片才有权执行的.

为了可以让你充分的明白而不是了解,举例: 线程数量 3个 分别是线程 a, b, c

当三个线程启动后,b线程先被cpu分配了随机时间片. 当b线程执行到 2 的位置的时候(即在刚执行完外面的if和同步代码块之间的位置的
时候时间片用完了),就会等待时间片到来.

这时a线程得到了随机时间片并开始执行,执行到同步代码块并且拿到了锁,在拿到锁之后却还没来得及执行里面的if的时候,a线程的时间片用完了在3的位置等待cpu的时间片.

这时c线程得到了cpu分配的时间片开始执行,当c线程在刚进去方法却还没来得执行外面的if的时候时间片用了,就在1的位置等待时间片到来.

这时a线程得到时间片开始运行,开始判断里面的if判断对象还没有创建,则创建
了对象然后返回了,这个时候在2位置的b线程得到了时间片,b线程开始运行,并进入了同步代码块那了锁,判断对象已经存在了(这位同学你
要注意的地方就在这!!!!!!)
就直接返回,这时在1位置的c线程得到时间片,开始判断外面if发现对象已经存在了就不执行同步代码块了就直
接返回对象了.

同学希望你能看懂过程....不要了解!

加油!!!
作者: 杨毅    时间: 2012-2-15 22:36
李杨 发表于 2012-2-15 22:04
同学你好:
          首先你需要明白synchronized的作用,意思是当线程得到了cpu分配的随机时间片后并获得了 ...

额...  我说的了解就是懂了 ..  先没考虑到有多个线程挂在第一个if 后面..       还是谢谢你的详细解释  




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