(阿里巴巴手冊)關於併發場景下,通過雙重檢查鎖實現延遲初始化的優化問題隱患的記錄

《阿里巴巴Java開發手冊》中有這麼一個推薦:
在這裏插入圖片描述
在這裏插入圖片描述
這種單例模式是我經常寫的,看到竟然是反例,網上查了查,還是有根據的。
這樣的問題在於初始化代碼:

instance = new Singleton();

JVM會將這段代碼分成三步去執行:

a.分配內存空間;

b.構造Singleton;

c.將instance指向構造的實例。

如果執行的過程是a->b->c的話,那上面的代碼是沒有問題的,但是有時JVM會基於***指令優化的目的將指令重排***,導致指令執行流程變爲a->c->b。這樣當線程A執行到4開始初始化單例對象的c流程時,線程B執行到1處,由於instance對象已經將內部指針指向分配的內存空間(即不爲null),會直接返回未完全構造好的實例,從而出錯。按照《手冊》的說法,修改後的代碼如下
在這裏插入圖片描述
由於volatile自帶的“禁止指令重優化”語義,初始化語句只能按照a->b->c的順序進行執行。

注:儘管這個問題看起來很簡單,但是我在本地沒有辦法重演這個bug,這個bug出現的關鍵時刻在於線程A在執行a->c->b鏈的c時,線程B將構造完的instance返回並使用纔會出錯,但是一般的場景下是沒有辦法在這麼短的時間間隔內捕獲到這個間隔的。不過出於保險的目的,單例模式的我還是加上volatile修飾符比較好。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章