雙重校驗鎖實現單例模式(對象單例,線程安全)

雙重校驗鎖實現單例模式:

public class Singleton {

    //採用volatile修飾
    private volatile static Singleton singleton;

    //構造方法私有化
    private Singleton(){}

    //雙重校驗鎖
    public static Singleton getInstance(){
        //先判斷對象是否已經實例過,沒有實例化過才進入加鎖代碼
        if(singleton == null){
            //類對象加鎖
            synchronized(Singleton.class){
                //再次判斷
                if (singleton == null){
                    singleton = new Singleton();
                }
            }
        }
        return singleton;
    }
}

注意:singleton 採用 volatile 修飾是很有必要的,因爲 singleton = new Singleton() 這句話可以分爲三步:

  1. 爲 singleton 分配內存空間;
  2. 初始化 singleton;
  3. 將 singleton 指向分配的內存空間。
    但是由於JVM具有指令重排的特性,執行順序有可能變成 1-3-2。 指令重排在單線程下不會出現問題,但是在多線程下會導致一個線程獲得一個未初始化的實例。例如:線程T1執行了1和3,此時T2調用 getInstance() 後發現 singleton 不爲空,因此返回 singleton, 但是此時的 singleton 還沒有被初始化。
    使用 volatile 會禁止JVM指令重排,從而保證在多線程下也能正常執行
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章