黑马程序员技术交流社区

标题: 懒汉式的问题 [打印本页]

作者: peku    时间: 2014-4-24 10:51
标题: 懒汉式的问题
本帖最后由 peku 于 2014-4-24 12:28 编辑
  1. class Single
  2. {
  3.         private static Single s = null;
  4.         private Single(){}
  5.         public static  Single getInstance()
  6.         {
  7.                 if(s==null)
  8.                 {
  9.                         synchronized(Single.class)
  10.                         {
  11.                                 if(s==null)//位置一
  12.                                         s = new Single();
  13.                         }
  14.                 }
  15.                 return s;
  16.         }
  17. }
复制代码

去掉位置一的那句判断行不行啊,我觉得好像没什么影响,请教各位了
作者: 钟成军    时间: 2014-4-24 11:21
哥,这个是懒汉式吧,去掉位置一可以,但是加上会更安全。
作者: peku    时间: 2014-4-24 11:23
钟成军 发表于 2014-4-24 11:21
哥,这个是懒汉式吧,去掉位置一可以,但是加上会更安全。

额,谢谢提醒,改过来了,加上为什么更安全呢,我觉得那句判断完全多余啊
作者: ☆枫の云    时间: 2014-4-24 11:31
本帖最后由 ☆枫の云 于 2014-4-24 11:42 编辑

视频上有讲解,涉及到多线程、CPU轮转机制,如果没有那一句,就可能会建立两个对象
  1. if(s==null) {
  2.       --A
  3.       synchronized(Single.class){
  4.           --B
  5.               s = new Single();
  6.       }
  7. }
复制代码

你看代码,如果没有那一句,虽然B在的时候A无法进来,但是B在new过对象以后,A同样也能进来,这样就建立两个对象,但是这是单例设计模式,只能存在一个对象,所以不符合设计理念。
但是加上if(s==null)就不一样了,B出去了,对象建立了,此时s就已经有值了,所以A进来也不能在创建对象了。

作者: 彭飞    时间: 2014-4-24 11:38
毕老师在视频上详细讲解了,
回头仔细看看吧。

主要就是安全性的问题。
作者: igi9009    时间: 2014-4-24 11:47
如果不加if(s==null),就存在安全隐患。比如说线程A和B都经过第一次if(s==null)判断后就跳转到线程C了,线程C没有跳转,直接进去newl了一个对象,然后线程C释放了。又轮到A进去了,这个时候虽然S不等于null了,但是A线程已经在s=null的时候就走完了判断,进入到同步代码区里,如果不再一次判断s是否等于null,A线程就会再new一个对象,同理B也会new一个对象,这样就不能保证对象唯一性了。所以获得锁进入之后也要再次判断。这样的安全隐患是有几率发生的,所以一定要两次判断。
作者: 秦久启    时间: 2014-4-24 11:54
如果没有那句的话,可能就会出现线程安全问题,也就是说可能会出现不止一个对象
class Single
{
private static Single s = null;
private Single(){}
public static Single getInstance()
{
  if(s==null)
  {
   synchronized(Single.class)
   {
   // if(s==null) 如果没有这句话的话,假设线程a先通过外层判断通过之后,然后进入到同步代码块里面,就在这个地方线程a等待了,释放了执行资格,
                          线程b也是先通过了外层判断,通过之后,由于同步代码块要判断锁,没有进去,假设现在线程a醒了,然后就new了一个,然后线程b也就
                          可以进入到同步代码块里面了,由于没有这句话,所以他还会执行s = new Single(); 所以就会出现了两个对象,出现了线程安全问题。


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






作者: peku    时间: 2014-4-24 12:26
☆枫の云 发表于 2014-4-24 11:31
视频上有讲解,涉及到多线程、CPU轮转机制,如果没有那一句,就可能会建立两个对象

你看代码,如果没有那 ...

明白了,没搞清楚外面和里面的if判断的各自作用,还是掌握得不够,思考得太草率了,谢谢了
作者: peku    时间: 2014-4-24 12:28
☆枫の云 发表于 2014-4-24 11:31
视频上有讲解,涉及到多线程、CPU轮转机制,如果没有那一句,就可能会建立两个对象

你看代码,如果没有那 ...

明白了,谢谢前辈,有点费脑子感觉这
作者: 大恶魔先森~    时间: 2014-4-24 13:48
  1. class Single
  2. {
  3.      privtate Single(){};
  4.      private static Single s=new Single();
  5.      public static Single getInstance()
  6.      {
  7.             if(s==null)
  8.             {
  9.                   Synchronized(Single.class)
  10.                   {
  11.                          if(s==null)//位置一
  12.                                       s = new Single();
  13.                         

  14. }
  15. }
  16. return s;

  17. }
  18. }
复制代码

如果去掉位置一的代码,当首先A进入线程并首先创建了对象,跳出了同步代码块,却并没有return s;的时候,B线程可以进来而且可以再次创建一个对象,这样就违背了单例设计模式的基本原则了.




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