Java併發-懶漢式單例設計模式加volatile的原因

懶漢式單例的double check、例一:

class SingletonClass{
    private static  SingletonClass instance = null;
 
    private SingletonClass() {}
 
    public static  SingletonClass getInstance() {
        if(instance==null) {
            synchronized ( SingletonClass.class) {
                if(instance==null)
                    instance = new  SingletonClass();//語句1
            }
        }
        return instance;
    }
}

 

 

上面的代碼在多線程下調用可能會報錯,具體報錯原因:

在語句1中並不是一個原子操作,在JVM中其實是3個操作:
1.給instance分配空間、
2.調用 Singleton 的構造函數來初始化、
3.將instance對象指向分配的內存空間(instance指向分配的內存空間後就不爲null了);
  在JVM中的及時編譯存在指令重排序的優化,也就是說不能保證1,2,3執行的順序,最終的執行順序可能是 1-2-3 也可能是 1-3-2。如果是 1-3-2,則在 3 執行完畢、2 未執行之前,被線程二搶佔了,這時 instance 已經是非 null 了(但卻沒有初始化),所以線程二會直接返回 instance,然後使用,然後順理成章地報錯。
  通過添加volatile就可以解決這種報錯,因爲volatile可以保證1、2、3的執行順序,沒執行玩1、2就肯定不會執行3,也就是沒有執行完1、2instance一直爲空,具體代碼如下:

class SingletonClass{
    private volatile static  SingletonClass instance = null;
 
    private SingletonClass() {}
 
    public static  SingletonClass getInstance() {
        if(instance==null) {
            synchronized ( SingletonClass.class) {
                if(instance==null)
                    instance = new  SingletonClass();
            }
        }
        return instance;
    }
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章