雙重檢查鎖提升併發

一個懶漢式單例緩存

 1 public class Singleton {
 2     private static volatile Singleton singleton = null;
 3 
 4     private Singleton(){}
 5 
 6     public static Singleton getSingleton(){
 7         if(singleton == null){
 8             synchronized (Singleton.class){
 9                 if(singleton == null){
10                     singleton = new Singleton();
11                 }
12             }
13         }
14         return singleton;
15     }    
16 }

 

 

這種編寫方式被稱爲「雙重檢查鎖」,主要在getSingleton()方法中,進行兩次null檢查。這樣能夠極大提高併發度,進而提高性能。畢竟在單例中new的狀況很是少,絕大多數都是能夠並行的讀操做,所以在加鎖前多進行一次null檢查就能夠減小絕大多數的加鎖操做,也就提升了執行效率。可是必須注意的是volatile關鍵字,該關鍵字有兩層語義。第一層語義是可見性,可見性是指在一個線程中對該變量的修改會立刻由工做內存(Work Memory)寫回主內存(Main Memory),因此其它線程會立刻讀取到已修改的值,關於工做內存和主內存可簡單理解爲高速緩存(直接與CPU打交道)和主存(平常所說的內存條),注意工做內存是線程獨享的,主存是線程共享的。volatile的第二層語義是禁止指令重排序優化,咱們寫的代碼(特別是多線程代碼),因爲編譯器優化,在實際執行的時候可能與咱們編寫的順序不一樣。編譯器只保證程序執行結果與源代碼相同,卻不保證明際指令的順序與源代碼相同,這在單線程並沒什麼問題,然而一旦引入多線程環境,這種亂序就可能致使嚴重問題。volatile關鍵字就能夠從語義上解決這個問題,值得關注的是volatile的禁止指令重排序優化功能在Java 1.5後才得以實現,所以1.5前的版本仍然是不安全的,即便使用了volatile關鍵字。安全

相關文章
相關標籤/搜索