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

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 杨芳 中级黑马   /  2013-2-24 08:54  /  1938 人查看  /  6 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

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;
}
}
上面的第二个if(s==null)有什么作用,是否可以不要?

6 个回复

倒序浏览
我想肯定有他的作用,就让我来给你解说下.:
class Single
{
private static Single s=null;
private Single(){}
public static  Single getInstance()
{
  if(s==null)
  {     有时候会发生这种情况..全部线程都判断s==null全部走到同步锁的时候,假设一个线程进去后, s就不等于空了..然后其他线程因为上面是if不是while就不会去判断上面那个条件,直接往下走, 假如同步锁里没有那个判断的话,就会出现.每个都要new一遍..会造成安全隐患., 但是可以有个简练代码方式..同步锁里面的if去掉.外部的if改为while.就好了.不仅代码简练,而且不会出现隐患.谢谢..表达的不好.
     synchronized( Single.class)
     {
     if(s==null)?????
     s=new Single();
     }
   }
  return s;
}
}
回复 使用道具 举报
上面的第二个if(s==null)是在第一次一个线程进入synchronized块时,这时肯定没有创建对象吧,所以s=new Single();。
这时有的线程还等待在synchronized块外,当第一个线程创建了s=Single()其他线程进入synchronized块就判断s==null是否相等,明显不等嘛!
所以就只创建一个对象了。
回复 使用道具 举报
谢谢!!!!!!
回复 使用道具 举报
如果第二个if语句不要会出现重复new对象的情况,如果两个线程同时停在synchronized( Single.class)的前一条语句,则都可以进入同步代码块new对象。
第一个if语句可以不要,但是每次都判断synchronized语句会降低效率,所以在外面先判断一次,如果不为null则不用判断synchronized。
回复 使用道具 举报
多线程嘛:假设线程比较多.Thread[] t=new Thread[100];
if(s==null)    //第三步,只要t[0]醒过来.外围的if()其他的t[2]-t[99]就不用判断了锁了.直接返回s;  //关键在于后面的线程不用判断同步锁了.所以提高了效率
  {    //t[1]也可以进到这里来,然后有同步锁,进不来.然后又wait()了. //第二步
     synchronized( Single.class)
     {
     if(s==null)?????        t[0]先进来了.然后wait()了.  //第一步
     s=new Single();
     }
   }
回复 使用道具 举报
同步代码块中的判断是为了延迟加载用的,即本类实例没有被实例化就创建一个本类实例,有就不创建,
同步外的判断是为了提高效率的,如果前面的线程已经创建的实例,后面的线程就不会进入同步代码块中了,
因为每次线程都要进入同步代码块才知道实例已经被创建了,每个线程都要判断锁,这样效率会比较低,外面
的判断是为了提高效率的,这样说你应该能明白了吧。
  1. public class SingleDemo {
  2.         private static SingleDemo s = null;
  3.         private SingleDemo(){}
  4.         public static  SingleDemo getInstance(){
  5.                 /*如果第一个线程获取到了单例的实例对象,
  6.                  * 后面的线程再获取实例的时候不需要进入同步代码块中了*/
  7.                 if(s == null){
  8.                         //同步代码块用的锁是单例的字节码文件对象,且只能用这个锁
  9.                         synchronized(SingleDemo.class){
  10.                                //这个判断是为了解决延迟加载的
  11.                                 if(s == null){
  12.                                         s = new SingleDemo();
  13.                                 }
  14.                         }
  15.                 }
  16.                 return s;
  17.         }
  18. }
复制代码
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马