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


餓漢模式:

class Single{

  private staitc final Single s= new Single();

  private Single(){}

  public static Single getSingle(){

    return s;

  }

}  

懶漢模式:

class Single{

  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小生店鋪

 

希望店鋪的資料能幫助到你!!!

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM