单例模式之懒汉的并发问题

饿汉模式:java

class Single{安全

  private staitc final Single s= new Single();多线程

  private Single(){}并发

  public static Single getSingle(){函数

    return s;this

  }spa

}  线程

懒汉模式:3d

class Single{htm

  private static Single s= null;

  private Single(){}

  public static Single getSingle(){

    if(s == null){

        -->A线程

        -->B线程

      s  =  new Single();

      return s;

    }  

  }

}  

在这里使用懒汉模式有一个安全性问题:

就是s为共享数据,可能会并发的访问getSingle()方法。当多线程访问时,一个A线程进来后,可能调用了sleep()方法在这里沉睡;一个B线程也可能在沉睡,当A线程醒来后,就会new一个对象,B线程醒来也会new一个对象;这样就不符合咱们单例模式的特色了。

解决方案:在getSingle()方法前增长synchronized进行同步

另外一个问题,当加了synchronized后,那么不少线程来访问时,都要判断一下锁是哪一个,这就形成速率降低,解决方案以下:

public staitc Single getSingle(){

  if(s == null){

    synchronized(Single.class){  -->B线程,等着A解锁才让进去

      if(s == null){

          -->A线程

        s = new Single();

      }

    }

  return s;

  }

}

思路:

当s == null时,A线程进来了,他加了一下锁后进入第二个if(s ==null){},而后沉睡;此时,B也经过了第一个if(s == null),当B玩下执行时,遇到了synchronized(),发现这里A进行了加锁,没办法B线程只能等着,等A把锁解了。此时,A线程醒来了,它new 了一个对象后,继续玩下执行,而后把锁解了,这是s不等于null了。B发现A解锁了,它继续往下执行,发现s不等于null了,那它直接返回了A建立的那个对象s。当c线程访问getSingle方法时,只需判断s是否为null,而不用去判断锁对象了。由于s不等于null了,因此直接返回对象,这样就提升了效率

懒汉模式是延迟加载的实例,面对多线程访问时,须要进行同步代码块,为了增长效率,又要使用双重判断

注意:非静态的同步函数对象是this,静态的同步函数对象是:字节码对象。即类.class;

 

 

Java小生店铺:

 

Pc端:http://shop125970977.taobao.com/index.htm

 

手机端:搜索 java小生店铺

 

但愿店铺的资料能帮助到你!!!

 

 

相关文章
相关标签/搜索