1. 程式人生 > >3.單例模式的多種寫法

3.單例模式的多種寫法

  • 不加同步的懶漢式是執行緒不安全的。比如,有兩個執行緒,一個是執行緒A,一個是執行緒B,它們同時呼叫getInstance方法,就可能導致併發問題。

  • 餓漢式是執行緒安全的,因為虛擬機器保證只會裝載一次,在裝載類的時候是不會發生併發的。

如何實現懶漢式的執行緒安全?

加上synchronized即可

public static synchronized Singleton getInstance(){}

但這樣會降低整個訪問的速度,而且每次都要判斷。可以用雙重檢查加鎖。

雙重加鎖機制,指的是:並不是每次進入getInstance方法都需要同步,而是先不同步,進入方法過後,先檢查例項是否存在,如果不存在才進入下面的同步塊,這是第一重檢查。進入同步塊後,再次檢查例項是否存在,如果不存在,就在同步的情況下建立一個例項。這是第二重檢查。

雙重加鎖機制的實現會使用一個關鍵字volatile,它的意思是:被volatile修飾的變數的值,將不會被本地執行緒快取,所有對該變數的讀寫都是直接操作共享記憶體,從而確保多個執行緒能正確的處理該變數。


/**
 * 雙重檢查加鎖的單例模式
 * @author dream
 *
 */
public class Singleton {

    /**
     * 對儲存例項的變數新增volitile的修飾
     */
    private volatile static Singleton instance = null;
    private Singleton(){

    }

    public static Singleton getInstance(){
        //先檢查例項是否存在,如果不存在才進入下面的同步塊
        if(instance == null){
            //同步塊,執行緒安全的建立例項
            synchronized (Singleton.class) {
                //再次檢查例項是否存在,如果不存在才真正的建立例項
                instance = new Singleton();
            }
        }
        return instance;
    }

}

一種更好的單例實現方式

public class Singleton {

    /**
     * 類級的內部類,也就是靜態類的成員式內部類,該內部類的例項與外部類的例項
     * 沒有繫結關係,而且只有被呼叫時才會裝載,從而實現了延遲載入
     * @author dream
     *
     */
    private static class SingletonHolder{
        /**
         * 靜態初始化器,由JVM來保證執行緒安全
         */
        private static final Singleton instance = new Singleton();
    }

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

    }

    public static Singleton getInstance(){
        return SingletonHolder.instance;
    }
}