如何理解單例的雙重檢查

2021-10-05 21:57:50 字數 980 閱讀 9528

根據進行了整理

先放上雙重檢查(dcl)的**

package com.sofmit.icbcepay.config.datasource;

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例項,這樣也還是違背了單例模式的初衷,所以這裡必須要使用第二次null檢查鎖定。

效能問題。因為對於單例模式的話,newsingleton()只需要執行一次就 ok 了,而如果沒有第一重singleton == null 的話,每一次有執行緒進入getinstance()時,均會執行鎖定操作來實現執行緒同步,這是非常耗費效能的,而如果我加上第一重singleton == null 的話,那麼就只有在第一次,也就是singletton ==null 成立時的情況下執行一次鎖定以實現執行緒同步,以後的話,便只要直接返回singleton 例項就 ok 了而根本無需再進入 lock語句塊了,這樣就可以解決由執行緒同步帶來的效能問題了。

如果去掉第一重singleton == null ,程式還是可以在多執行緒下完好的執行的。

單例模式的雙重檢查

單例模式 public class singleton public static singleton getinstance return uniqueinstance 其中有兩次判斷是否為空的語句,第一次是為了提高效率,避免每次都要執行同步 塊,第二次判空,是為了避免多執行緒帶來的不安全,當兩個...

單例模式之雙重檢查

在實現單例模式時,如果未考慮多執行緒的情況,就容易寫出下面的錯誤 public class singleton public singleton getinstance return uniquesingleton 在多執行緒的情況下,這樣寫可能會導致uniquesingleton有多個例項。比如下...

單例模式 雙重檢查鎖

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