關於雙重檢驗鎖,首先簡單來看一個小例子,代碼如下:
public class Singleton{
private static Singleton instance = null;
private Singleton(){}
public static Singleton getInstance(){
if (instance == null) {//e1
synchronized(Singleton.class){
if (instance == null) {//e2
instance = new Singleton();
}
}
}
return instance;
}
}
雙重檢驗鎖是對同步塊加鎖的方法。爲什麼會稱爲雙重檢驗,因爲有兩次對 instance == null的檢查,一次中同步塊中一次中同步塊外部。
對於兩次instance的是否爲空的判斷解釋:
1.爲何在synchronization外面的判斷?
爲了提高性能!如果拿掉這次的判斷那麼在行的時候就會直接的運行synchronization,所以這會使每個getInstance()都會得到一個靜態內部鎖,這樣的話鎖的獲得以及釋放的開銷(包括上下文切換,內存同步等)都不可避免,降低了效率。所以在synchronization前面再加一次判斷是否爲空,則會大大降低synchronization塊的執行次數。
2.爲何在synchronization內部還要執行一次呢?
因爲可能會有多個線程一起進入同步塊外的 if,如果在同步塊內不進行二次檢驗的話就會生成多個實例了。
PS:雙重檢驗情況下,保存實例的唯一的靜態變量要用volatile修飾,volatile能禁止指令重排。