雙重鎖實現單例時遭到質疑,既是:雙重鎖也無法保證單例模式!
原因是:指令會重排序,普通的變量僅僅會保證該方法在執行時,所有依賴的賦值結果是正確的,但不會保證執行順序!
為什么會重排序:指令重排序是指cpu采用了允許將多條指令不按照程序的順序分開發送各相應電路單元處理,cpu不會任意排序(深入java虛擬機第12章),但需要重排序提高性能。
怎么解決,標題也寫明白了。
使用volatile關鍵字!
為什么使用volatile關鍵字可以實現:此關鍵字會禁止指令重排序,即:增加了內存屏障!
如果是一個cpu內存屏障是毫無意義的,如果是多cpu訪問同一塊內存,並且其中一個在觀測另一個,就需要內存屏障來保證一執行了。
如果你打開編譯后的代碼清單,會看到加入volatile關鍵字的變量會多一條指令:lock addl $0x0 ,(%esp)
此指令很有意義:lock addl $0x0 指令的作用是使當前cpu的cache值寫入內存,該寫入操作也會引起其他cpu或者內核無效化其cache,既是是做了一個空操作(store、write),可以讓volatile變量對其他cpu立即可見!

1 public class Singleton { 2 3 private volatile static Singleton singleton = null; 4 5 public static Singleton getSingleton() { 6 if (singleton == null) { 7 synchronized (Singleton.class) { 8 if (singleton == null) { 9 singleton = new Singleton(); 10 } 11 } 12 } 13 return singleton; 14 } 15 }
另外:volatile屏蔽指令重排序的語義,在jdk1.5中才被完全修復!