單例模式之懶漢的併發問題

餓漢模式: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小生店鋪

 

但願店鋪的資料能幫助到你!!!

 

 

相關文章
相關標籤/搜索