/**
* 單例模式-雙重校驗鎖(懶漢模式)**/
public class singleton ; //私有化構造方法
private static volatile singleton singleton=null;
public static singleton getinstance()}}
return singleton;
}public static void main(stringargs)
}).start();}}
}
第一步:私有化構建方法;
第二步:宣告物件為空(關鍵字:volatile)
第三步:雙層檢驗:例項化空物件引用
注意事項:
問題:為什麼需要兩次判斷if(singleton==null)?
第一次校驗:由於單例模式只需要建立一次例項,如果後面再次呼叫getinstance方法時,則直接返回之前建立的例項,因此大部分時間不需要執行同步方法裡面的**,大大提高了效能。如果不加第一次校驗的話,那跟上面的懶漢模式沒什麼區別,每次都要去競爭鎖。
第二次校驗:如果沒有第二次校驗,假設執行緒t1執行了第一次校驗後,判斷為null,這時t2也獲取了cpu執行權,也執行了第一次校驗,判斷也為null。接下來t2獲得鎖,建立例項。這時t1又獲得cpu執行權,由於之前已經進行了第一次校驗,結果為null(不會再次判斷),獲得鎖後,直接建立例項。結果就會導致建立多個例項。所以需要在同步**裡面進行第二次校驗,如果例項為空,則進行建立。注意:private static volatile singleton3 singleton=null;需要加volatile關鍵字,否則會出現錯誤。
問題的原因在於jvm指令重排優化的存在。在某個執行緒建立單例物件時,在構造方法被呼叫之前,就為該物件分配了記憶體空間並將物件的字段設定為預設值。此時就可以將分配的記憶體位址賦值給instance欄位了,然而該物件可能還沒有初始化。若緊接著另外乙個執行緒來呼叫getinstance,取到的就是狀態不正確的物件,程式就會出錯。靜態內部類:同樣也是利用了類的載入機制,它與餓漢模式不同的是,它是在內部類裡面去建立物件例項。這樣的話,只要應用中不使用內部類,jvm就不會去載入這個單例類,也就不會建立單例物件,從而實現懶漢式的延遲載入。也就是說這種方式可以同時保證延遲載入和執行緒安全。
單例模式 雙層檢驗鎖 volatile
package com.utils.threads public class dl return instance public static void main string args 分析 加volatile的必要性 原因在於指令重排的存在,加入volatile可以禁止指令重排 當某乙個執行緒執...
單例模式 懶漢式 餓漢式和雙層鎖模式
單例就是該類只能返回乙個例項。單例所具備的特點 1.私有化的建構函式 2.私有的靜態的全域性變數 3.公有的靜態的方法 單例分為懶漢式 餓漢式和雙層鎖式 懶漢式比較懶,只有當呼叫getinstance的時候,才回去初始化這個單例 author dym date 2020 12 20 16 07 pu...
java單例模式中的雙重檢驗鎖
public class doublecheck public static doublecheck getsingleton return instance 首先判斷instance是否為null,如果確實為null,則進入乙個synchronize包圍的 塊,相當於上了鎖,進入了臨界區,為了防止...