基於DCL的單例懶漢模式實現

2021-10-22 09:47:19 字數 1950 閱讀 9433

全稱是double check lock,即雙重鎖檢查,是在進入同步**塊之前和之後都進行一次檢查操作,之所以在進入同步**塊再檢查一次的原因是,有可能在外部檢查後,獲取同步鎖之前,當前持有鎖的執行緒,在釋放鎖之前已經改變了系統狀態,如下**:

volatile

int x =1;

// 第一次檢查

if(x ==1)

}}

如下時間線:

時間操作

x的值t1

執行緒a成功進入同步**塊,開始操作1t2

執行緒b判斷第乙個x == 1為true,但是阻塞1t3

執行緒a執行x == 2修改x的值為22t4

執行緒a進入同步**塊,再次判斷x == 1為false,結束

2如果是沒有再次x == 1的檢查,則就產生程式錯誤了。

2.1:**

public

class

dclhungry

public

static dclhungry getinstance()

}}return instance;

}}

2.2:測試
@test

public

void

testdclhungry()

,"執行緒!!!"

+ i)

.start()

;}}

多次執行:

例項初始化開始了

例項初始化結束了

執行緒!!!0-yudaosourcecode.dcltest.dclhungry@70107534

執行緒!!!1-yudaosourcecode.dcltest.dclhungry@70107534

執行緒!!!2-yudaosourcecode.dcltest.dclhungry@70107534

例項初始化開始了

例項初始化結束了

執行緒!!!0-yudaosourcecode.dcltest.dclhungry@227d344b

執行緒!!!2-yudaosourcecode.dcltest.dclhungry@227d344b

執行緒!!!1-yudaosourcecode.dcltest.dclhungry@227d344b

可以看到只建立了一次。我們可以將**修改為如下,即去掉第二次檢查:

public

static dclhungry getinstance()

}}return instance;

}

多次執行:

例項初始化開始了

例項初始化結束了

例項初始化開始了

執行緒!!!0-yudaosourcecode.dcltest.dclhungry@227d344b

執行緒!!!1-yudaosourcecode.dcltest.dclhungry@227d344b

例項初始化結束了

執行緒!!!2-yudaosourcecode.dcltest.dclhungry@17a4fb6d

以上結果初始化了2次

例項初始化開始了

例項初始化結束了

例項初始化開始了

例項初始化結束了

例項初始化開始了

例項初始化結束了

執行緒!!!1-yudaosourcecode.dcltest.dclhungry@1a4555f8

執行緒!!!0-yudaosourcecode.dcltest.dclhungry@227d344b

執行緒!!!2-yudaosourcecode.dcltest.dclhungry@17a4fb6d

以上結果初始化了3次

dcl單例模式

有時候我們需要對外呈現只有乙個物件,簡單來說就是講物件私有化,像資料那樣,只能通過get方法得到。這裡使用doublechecking來進行該操作,即在get方法裡面加入兩個判斷該物件是否為空,同時為了避免指令重排導致執行緒獲得空物件,加入volatile,而且私有化構造器。public class...

DCL單例模式

單例模式 外部不能new物件,類的內部有且只有乙個物件,僅僅用乙個靜態方法與外界進行互動。public class doublecheckedlocking 外部只能通過這個get方法和此物件進行交流 public static doublecheckedlocking getinstance 繫結...

懶漢單例模式

單例設計模式 懶漢單例模式 能夠保證在只有用它的時候才建立它的物件。目前還不能保證乙個類在記憶體中只有乙個物件。懶漢單例模式設計步驟 1 私有化建構函式 2 生命本類的引用型別變數,但是不要建立物件 3 提供公共的靜態方法獲取本類的物件,獲取之前先判斷是否已經建立了本類的物件,如果已經建立了,那麼直...