單例模式

來源:互聯網
上載者:User

標籤:

單例模式:保證一個類僅有一個執行個體,並提供一個訪問它的全域訪問點。

通常我們可以讓一個全域變數使得同一個對象被訪問,但是它不能防止你執行個體化多個對象,一個最好的辦法就是,讓類自身負責儲存它的唯一執行個體。這個類可以保證沒有其它執行個體可以被建立,並且它可以提供一個訪問該執行個體的方法。

舉例如下:

    /// <summary>    /// 普通的單例模式    /// 通過將建構函式私人化,並提供私人靜態變數和靜態方法達到對執行個體化的控制    /// 這種方式產生的對象是在使用時才被執行個體化,因此被稱為懶漢式    /// </summary>    class CommonSingleton    {        private static CommonSingleton instance;        private CommonSingleton()        { }        public static CommonSingleton GetInstance()        {            if (instance == null)            {                instance = new CommonSingleton();            }            return instance;        }    }

 用戶端調用:

            CommonSingleton commonSingleton1 = CommonSingleton.GetInstance();            CommonSingleton commonSingleton2 = CommonSingleton.GetInstance();            if (commonSingleton1==commonSingleton2)            {                Console.WriteLine("commonSingleton is the same one.");             }

運行結果為:  commonSingleton is the same one.

 

在多線程的程式中,多個線程同時訪問Singleton的GetInstance()放法,還是有可能造成建立多個執行個體,這是需要引入鎖(lock)機制,lock是確保當一個線程位於代碼的臨界區時,另一個線程不進入臨界區,如果其他線程試圖進入鎖定的代碼,則它將一直等待,直到該對象被釋放,舉例如下:

class LockSingleton    {        private static LockSingleton instance;        //程式運行時建立的一個靜態唯讀進程輔助對象        private static readonly object syncRoot = new object();        private LockSingleton()        { }        public static LockSingleton GetInstance()        {                        lock (syncRoot)            {                //同一個時刻,這部分程式只有一個線程可以進入                if (instance == null)                {                    instance = new LockSingleton();                }                return instance;            }        }    }

這段代碼使得對象的建立由最先進入的那個線程建立,以後的線程在進入時不會再建立對象執行個體了。

但是每次調用GetInstance方法時都需要Lock,即線程直線可能會被阻塞,這會影響效能,更好的辦法是採用雙重鎖定,舉例如下:

    /// <summary>    /// Double-Check Locking    /// 對鎖定方法的改進,僅在執行個體為null時加鎖,提高了代碼的效率    /// </summary>    class DoubleCheckLockSingleton    {        private static DoubleCheckLockSingleton instance;        private static readonly object syncRoot = new object();        private DoubleCheckLockSingleton()        { }        public static DoubleCheckLockSingleton GetInstance()        {            //先判斷執行個體是否存在,不存在再加鎖處理            if (instance == null)            {                lock (syncRoot)                {                    if (instance == null)                    {                        instance = new DoubleCheckLockSingleton();                    }                }            }            return instance;        }    }

 這樣即提高了效率,又解決了多線程下的單例問題。

在C#中提供了一種“靜態初始化”方法,這種方法不需要開發人員顯示的編寫安全執行緒代碼,即可解決多線程環境下的不安全問題,舉例如下:

    /// <summary>    /// 靜態初始化方法實現單例模式    /// 使用sealed關鍵字避免類的繼承,使用readonly使得變數只能在靜態初始化期間或類建構函式中分配變數    /// 私人的構造方法使得不能再類本身以外的地方執行個體化Singleton類    /// 這種方法中的執行個體是在類被載入時就執行個體化,因此被稱為餓漢模式    /// </summary>    sealed class Singleton    {        //第一次引用類的任何成員時建立執行個體,公用語言運行庫負責處理變數的初始化        private static readonly Singleton instance = new Singleton();        private Singleton()        { }        public static Singleton GetInstance()        {            return instance;        }    }

 由於餓漢式即靜態初始化方式是在類一載入就執行個體化對象,所以要提前佔用系統資源,而懶漢式又需要雙重鎖定機制保證安全執行緒,所以採用哪種方式,取決於實際需要。從C#語言角度來講,餓漢式的單例類已經能夠滿足我們的需求了。 

  

 

單例模式

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.