引言
在學習創(chuàng)建型模式中的單例模式的時候榄檬,我們都會接觸到雙重檢測鎖實現(xiàn)的單例模式(飽漢模式),代碼如下:
ublic class Singleton {
/**
* 飽漢模式(雙重檢測鎖)
*/
private Singleton(){};
private static volatile Singleton instance = null;
public static Singleton getInstance(){
if(instance==null){
synchronized (Singleton.class){
if(instance==null){
instance = new Singleton();
}
}
}
return instance;
}
}
可是為什么要使用volatile以及為什么要檢測兩次instance呢熙宇?
為什么使用Volatile
我們不妨先說一下volatile的作用
- 防止指令重排
- 指明被修飾的變量是不安全的形病,每次都必須到內(nèi)存中讀取
在單例模式中,我們使用volatile是為了防止指令重排屡谐,想象一下這種情況:當實例還沒有創(chuàng)建的時候皮仁,線程A獲得了synchronized鎖籍琳,創(chuàng)建對象菲宴,雖然synchronized鎖保證了操作的原子性,但是沒有保證指令重排的正確性趋急,如果構造函數(shù)中的操作很多喝峦,這個時候就可能出現(xiàn)instance已經(jīng)被賦值了,但是還沒有實例化完呜达,這個時候如果線程B進入了谣蠢,判斷(instance==null)的時候就會誤以為instance存在,直接返回查近,造成錯誤眉踱。
為什么要校驗兩次
想象一下這種情況:有兩個線程同時通過了第一次判斷instance==null,假設線程B獲得了鎖,此時線程A就處于等待狀態(tài)霜威。當線程B創(chuàng)建完實例之后谈喳,線程A可以獲得這把鎖,如果在這里沒有第二次判斷的話戈泼,線程A也會創(chuàng)建一個實例婿禽,這明顯就與單例模式的初衷不符。
以上是我的個人理解大猛。