DLC單例模式

2021-10-09 19:16:28 字數 1965 閱讀 3928

首先對文章標題進行一下解讀

dlc:

doublechecking—>雙重檢測,用以避免不必要的同步

單例模式:

一般常見的有懶漢式與惡漢式兩種,這裡方便讀者理解,主要介紹懶漢式的單例模式。

懶漢式的單例模式主要也就是指:

構造器私有化—>避免外部new物件

提供私有靜態屬性—>儲存物件的位址

提供公共靜態方法—>獲取屬性

public

class

t//提供公共靜態方法--->獲取屬性

public

static t gett()

return t;

}public

static

void

main

(string[

] args)

}

上面就是乙個簡單的懶漢式單例模式的**,這個**在初學的只有乙個主線程時執行不會出現問題,但是在多執行緒場景下時就會出現問題

if

(null==t)

當多個執行緒呼叫該方法時,很可能會出現一種情形:假設有a,b兩個執行緒,a執行緒首先呼叫該方法,那麼此時a執行緒一定會去構造物件t;當b執行緒再呼叫該方法時,如果由於網路延遲或者記憶體讀寫速度,導致此時t物件的引用未傳回,則此時if判斷式的結果仍然為true,b執行緒也會去再構造乙個t的物件,此時就導致多執行緒之間的資料傳遞可能會出現問題。

此時,我們可以想到利用synchronized關鍵字對gett()進行加鎖的操作,基於優化的考慮,我們此處沒必要對整個方法加鎖,可以利用synchronized塊對部分**加鎖。

public

static t gett()

}return t;

}

如上述**,這裡synchronized鎖的是類的模子,也就是類鎖。

類鎖是鎖住整個類,當有多個執行緒來宣告這個類的物件時候將會被阻塞,直到擁有這個類鎖的物件銷毀或者主動釋放了類鎖,這個時候在被阻塞的執行緒被挑選出乙個占有該類鎖,宣告該類的物件。其他執行緒繼續被阻塞。

這個時候,dlc單例模式的雛形其實已經基本搭建完成,dlc的雙重檢測其實就是對於**加鎖後的一種優化。

if

(null!=t)

/*doublechecking 雙重檢測--->避免不必要的同步*/

synchronized

(t.class

)}

當t物件已經被其他執行緒例項化,且引用成功傳遞回來後,當之後其他執行緒再次呼叫訪問時,其實就沒必要再加鎖進行同步(在高併發時會嚴重影響效率)

這個時候,**的功能看似已經基本完成,但是不要忘記jvm對於**的重排機制的影響!

在new乙個物件時,主要有三步操作

1、開闢空間 2、初始化物件資訊 3、返回物件的位址給引用

當jvm進行重排優化時,2,3兩步的順序可能會顛倒

還是拿前面的例子來說,存在a,b兩個執行緒,a執行緒首先呼叫該方法,如果jvm對new物件時的操作進行了重排,則此時b執行緒拿到的t物件的引用有可能是乙個空物件。這裡又會出現b執行緒重新new乙個t物件的問題。

因此,這裡就需要加入volatile關鍵字對t物件進行同步,對於t物件的操作將在其他執行緒呼叫t時同步更新。

public

class

t//提供公共靜態方法--->獲取屬性

public

static t gett()

/*********************/

synchronized

(t.class)}

return t;

}public

static

void

main

(string[

] args)

}

單例模式 單例模式

餓漢式 急切例項化 public class eagersingleton 2.宣告靜態成員變數並賦初始值 類初始化的時候靜態變數就被載入,因此叫做餓漢式 public static eagersingleton eagersingleton new eagersingleton 3.對外暴露公共的...

單例 單例模式

簡單的實現乙個單例 instancetype sharedinstance return instance 真正的單例模式 myclass sharedinstance return instance id allocwithzone nszone zone return nil id copywi...

單例模式 懶漢式單例模式

單例模式有餓漢時模式和懶漢式 單例模式也就是說同一類只返回乙個物件供外部類使用 懶漢式即延遲初始化單例。在多執行緒環境下,簡單的懶漢式會有執行緒安全。懶漢式單例模式解決線性安全問題如下 1 使用雙重檢查鎖機制解決執行緒安全問題。2 單例模式還有更好的解決方案,即使用靜態類方式。懶漢式單例模式典型 p...