常用設計模式-單例模式(Singleton pattern)

Zyiyi11200發表於2024-07-27

常用設計模式-單例模式(Singleton pattern)

一、單例模式目的

使用單例模式第一步要了解其作用,單例理解為一個例項(one instance)。保證一個類只有一個它的例項。在實際開發中,如執行緒池,資料庫連線物件等。

二、實現思路

為了保證 one class one instance

①則需要保證例項全域性唯一,保證例項全域性唯一的方式這裡選用的是可以使用 static 關鍵字修飾例項引用,靜態欄位全域性共享,但是需要保證該例項引用自始至終只引用一個例項。例項可以在 bean 建立時建立(飢餓模式),也可以在需要時才例項化(減輕伺服器壓力,懶惰模式)。

②並且建構函式只能私有化,避免任何執行緒都能 new 一個例項

③其次開放一個訪問入口,即屬於類的 get 靜態方法,用 static 修飾。

④獲取例項時需要先判斷例項已經建立才獲取,未建立需要建立唯一的例項,下面為雙重驗證 + volatile方式建立例項的實現

雙重驗證 + volatile

public Class Singleton(){
    private volatile static Singleton uniqueInstance;

private Singleton() {
}

public static Singleton getUniqueInstance() {
   //先判斷物件是否已經例項過,沒有例項化過才進入加鎖程式碼
    if (uniqueInstance == null) {
        //類物件加鎖
        synchronized (Singleton.class) {
            if (uniqueInstance == null) {
                uniqueInstance = new Singleton();
            }
        }
    }
    return uniqueInstance;
}
}

如果單使用雙重驗證,由於已獲得鎖的執行緒在建立例項時,執行緒分三步執行指令(分配記憶體空間地址,初始化例項,引用指向記憶體空間地址),三步操作並非按排序進行,有可能先執行了第 3 步再執行第 2 步,另一執行緒在第一次驗證時判斷到例項引用不為空,即返回,執行緒對該例項引用的後續使用會造成空指標異常 。因此需要使用 volatile 保證指令不被重排序

但如果單使用 volatile,則不能保證執行緒例項化時這個操作的原子性。因此雙重驗證 + volatile便是處於這樣的考慮。

相關文章