在多執行緒中建立單例模式的雙重鎖定

2021-06-28 02:14:50 字數 1412 閱讀 8651

public class singleton

public static singleton getinstance() }

}return singleton; }

}為何要使用雙重檢查鎖定呢?上文已經大概說了一下。

考慮這樣一種情況,就是有兩個執行緒同時到達,即同時呼叫 getinstance() 方法,

此時由於

singleton == null ,所以很明顯,兩個執行緒都可以通過第一重的

singleton == null ,

進入第一重 if 語句後,由於存在鎖機制,所以會有乙個執行緒進入 lock 語句並進入第二重

singleton == null ,

而另外的乙個執行緒則會在 lock 語句的外面等待。

而當第乙個執行緒執行完 new 

singleton()語句後,便會退出鎖定區域,此時,第二個執行緒便可以進入 lock 語句塊,

此時,如果沒有第二重

singleton == null 的話,那麼第二個執行緒還是可以呼叫 new 

singleton ()語句,

這樣第二個執行緒也會建立乙個

singleton例項,這樣也還是違背了單例模式的初衷的,

所以這裡必須要使用雙重檢查鎖定。

細心的朋友一定會發現,如果我去掉第一重 singleton == null ,

程式還是可以在多執行緒下完好的執行的,

考慮在沒有第一重 singleton == null 的情況下,

當有兩個執行緒同時到達,此時,由於 lock 機制的存在,第乙個執行緒會進入 lock 語句塊,並且可以順利執行 new singleton(),

當第乙個執行緒退出 lock 語句塊時, singleton 這個靜態變數已不為 null 了,所以當第二個執行緒進入 lock 時,

還是會被第二重 singleton == null 擋在外面,而無法執行 new singleton(),

所以在沒有第一重 singleton == null 的情況下,也是可以實現單例模式的?那麼為什麼需要第一重 singleton == null 呢?

這裡就涉及乙個效能問題了,因為對於單例模式的話,new singleton()只需要執行一次就 ok 了,

而如果沒有第一重 singleton == null 的話,每一次有執行緒進入 getinstance()時,均會執行鎖定操作來實現執行緒同步,

這是非常耗費效能的,而如果我加上第一重 singleton == null 的話,

那麼就只有在第一次,也就是 singletton ==null 成立時的情況下執行一次鎖定以實現執行緒同步,

而以後的話,便只要直接返回 singleton 例項就 ok 了而根本無需再進入 lock 語句塊了,這樣就可以解決由執行緒同步帶來的效能問題了。

單例模式 多執行緒 雙重鎖定

using system using system.collections.generic using system.linq using system.text using system.threading.tasks namespace singleton model 此方法是獲得本類例項的唯一...

單例模式中的雙重校驗鎖

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

單例模式 雙重檢查鎖

單例模式分為餓漢式和懶漢式。餓漢式是事先分配記憶體,提前建立。這樣的方式為到位占用資源,當這種比較多時,會占用很多記憶體。懶漢式是在被呼叫的時候進行。這種在併發時又會導致問題。比較穩妥的辦法是在懶漢式的基礎上加上鎖,然後進行雙重檢查,這種springioc容器式單例也是用這種雙重檢查來避免執行緒衝突...