單例模式 雙重校驗鎖

2022-05-06 15:21:08 字數 1082 閱讀 5401

/**

* 單例模式-雙重校驗鎖

* @author szekinwin**/

public class singleton3 ;             //私有化構造方法

private static volatile singleton3 singleton=null;

public static singleton3 getinstance()}}

return singleton;

}public static void main(stringargs)

}).start();}}

}注意事項:

問題:為什麼需要兩次判斷if(singleton==null)?

分析:第一次校驗:由於單例模式只需要建立一次例項,如果後面再次呼叫getinstance方法時,則直接返回之前建立的例項,因此大部分時間不需要執行同步方法裡面的**,大大提高了效能。如果不加第一次校驗的話,那跟上面的懶漢模式沒什麼區別,每次都要去競爭鎖。

第二次校驗:如果沒有第二次校驗,假設執行緒t1執行了第一次校驗後,判斷為null,這時t2也獲取了cpu執行權,也執行了第一次校驗,判斷也為null。接下來t2獲得鎖,建立例項。這時t1又獲得cpu執行權,由於之前已經進行了第一次校驗,結果為null(不會再次判斷),獲得鎖後,直接建立例項。結果就會導致建立多個例項。所以需要在同步**裡面進行第二次校驗,如果例項為空,則進行建立。

需要注意的是,private static volatile singleton3 singleton=null;需要加volatile關鍵字,否則會出現錯誤。問題的原因在於jvm指令重排優化的存在。在某個執行緒建立單例物件時,在構造方法被呼叫之前,就為該物件分配了記憶體空間並將物件的字段設定為預設值。此時就可以將分配的記憶體位址賦值給instance欄位了,然而該物件可能還沒有初始化。若緊接著另外乙個執行緒來呼叫getinstance,取到的就是狀態不正確的物件,程式就會出錯。

(4)靜態內部類:同樣也是利用了類的載入機制,它與餓漢模式不同的是,它是在內部類裡面去建立物件例項。這樣的話,只要應用中不使用內部類,jvm就不會去載入這個單例類,也就不會建立單例物件,從而實現懶漢式的延遲載入。也就是說這種方式可以同時保證延遲載入和執行緒安全。

單例雙重校驗鎖

public class singledoublelock 1 第一次校驗 因為該類是單例的只建立一次,大部分時間single都不為空,所以不會進行第一次檢驗的 塊內部,從而提高效率 2 第二次校驗 如果single為空,執行緒t1,t2進入第一次檢驗的 塊,t1執行synchronized 塊 n...

雙重校驗鎖實現單例模式

1 先上 public class singleton public static singleton getinstance return instance 2 分析 第一次校驗 instance null 單例模式只需要建立乙個例項,假如例項不為空則不需要去競爭鎖,提高效能 第二次校驗 inst...

單例模式中的雙重校驗鎖

單執行緒的時候 class foo return helper 這段在使用多執行緒的情況下無法正常工作。在多個執行緒同時呼叫gethelper 時,必須要獲取鎖,否則,這些執行緒可能同時去建立物件,或者某個執行緒會得到乙個未完全初始化的物件。鎖可以通過代價很高的同步來獲得,就像下面的例子一樣。這樣寫...