線程安全的單例模式 雙重效驗鎖


線程安全的單例模式 雙重效驗鎖

 

1.單例模式:確保一個類只有一個實例,自行實例化並向系統提供這個實例(舉例 例如有三個線程 使用靜態方法,讓所創建出來的對象名來調取每一個線程。)

2.單例模式分類:餓單例模式(類加載時實例化一個對象給自己的引用),懶單例模式(調用取得實例的方法如getInstance時才會實例化對象)(java中餓單例模式性能優於懶單例模式,c++中一般使用懶單例模式)

3.單例模式要素:

私有構造方法

私有靜態引用指向自己實例

以自己實例為返回值的公有靜態方法

餓單例模式:

public static HungrySingleton getInstance {
    private static HungrySingleton sc  = new HungrySingleton();
    private HungrySingleton(){
    }
    public static HungrySingleton getInstance(){
        return sc;
    }
}

在程序執行開始的時候,餓單例模式就會new 出新的對象;這種寫法就是所謂的飢餓模式,每個對象在沒有使用之前就已經初始化了。這就可能帶來潛在的性能問題:如果這個對象很大呢?沒有使用這個對象之前,就把它加載到了內存中去是一種巨大的浪費。

懶單例模式

public class Singleton {
    private Singleton(){

    }
    private static Singleton sc;
    public static synchronized Singleton getInstance(){   //多線程時注意線程安全
        if(sc == null){
            sc= new Singleton();
        }
        return sc;
    }
}

在程序執行開始的時候,只有在你需要用的時候才會new新對象  意思為空的時候才會new出新對象

雙重效驗鎖

public static SingleClass getInstance(){
        if(sc==null){  //第一次校驗
            synchronized (SingleClass.class){ //同步代碼塊
                 if(sc==null){  //第二次校驗
                     sc=new SingleClass(); //創建實例
                 }
            }
        }
        return sc;
    }

此寫法保證了,當多個進程進入第一個判斷鎖時,會被同步機制隔離,只有一個程序進入新建對象,再其他線程進入時,sc已經不為null,因此不會新建多個對象。這種方法就叫做雙重檢查鎖,但是也有一個問題,就是java是實行無序寫入的機制,在某個線程執行//2代碼的過程中,sc被賦予了地址,但是singleton對象還沒構造完成時,如果有線程訪問了代碼//1此時判斷sc不為空,但是方法返回的是一個不完整對象的引用。此時可能會產生錯誤!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM