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