C#實(shí)現(xiàn)單例模式的多種方式
什么是單例模式?
這里我就不做過多的解釋了, 畢竟關(guān)于Singleton的資料實(shí)在是太多太多了。點(diǎn)擊這里
簡(jiǎn)單的思路就是, 創(chuàng)建對(duì)象單例的動(dòng)作轉(zhuǎn)移到另外的行為上面, 利用一個(gè)行為去創(chuàng)建對(duì)象自身, 如下:
public class Singleton { private Sington() { } private static Singleton _Singleton = null; public static Singleton CreateInstance() { if (_Singleton == null) { Console.WriteLine("被創(chuàng)建"); _Singleton = new Singleton(); } return _Singleton; } }
這樣寫看上去是沒有問題, 但是有沒有那種可能, 同時(shí)兩個(gè)動(dòng)作都判斷這個(gè)對(duì)象為空, 那么這個(gè)對(duì)象就會(huì)被創(chuàng)建2次?是的, 多線程中, 這樣是無法保證單例。
就像這樣, 同時(shí)創(chuàng)建多個(gè)線程去創(chuàng)建這個(gè)對(duì)象實(shí)例的時(shí)候, 會(huì)被多次創(chuàng)建, 這個(gè)時(shí)候, 對(duì)代碼改進(jìn)一下。
public class Singleton { private Sington() { } private static Singleton _Singleton = null; private static object Singleton_Lock = new object(); //鎖同步 public static Singleton CreateInstance() { lock (Singleton_Lock) { Console.WriteLine("路過"); if (_Singleton == null) { Console.WriteLine("被創(chuàng)建"); _Singleton = new Singleton(); } } return _Singleton; } }
調(diào)試代碼:
TaskFactory taskFactory = new TaskFactory(); List<Task> taskList = new List<Task>(); for (int i = 0; i < 5; i++) { taskList.Add(taskFactory.StartNew(() => { Singleton singleton = Singleton.CreateInstance(); })); }
結(jié)果:
上面, 我們創(chuàng)建了多個(gè)線程,同時(shí)去創(chuàng)建這個(gè)對(duì)象的實(shí)例, 在第二次,對(duì)象命名已經(jīng)被創(chuàng)建了, 盡管只創(chuàng)建了一次滿足了我們的需求, 但是我們已知對(duì)象被創(chuàng)建了, 還需要進(jìn)來做不必要的動(dòng)作嗎?
我們都知道, 同步鎖為了達(dá)到預(yù)期的效果, 也是損耗了性能的, 那么下面的輸出, 很顯然是沒必要的動(dòng)作, 所以我們優(yōu)化一下。
public class Singleton { private static Singleton _Singleton = null; private static object Singleton_Lock = new object(); public static Singleton CreateInstance() { if (_Singleton == null) //雙if +lock { lock (Singleton_Lock) { Console.WriteLine("路過。"); if (_Singleton == null) { Console.WriteLine("被創(chuàng)建。"); _Singleton = new Singleton(); } } } return _Singleton; } }
結(jié)果:
很顯然, 這樣達(dá)到了我們的預(yù)期, 對(duì)象在被創(chuàng)建后, 就沒必要做多余的行為。
利用靜態(tài)變量實(shí)現(xiàn)單例模式
public sealed class Singleton { private Singleton() { } private static readonly Singleton singleInstance = new Singleton(); public static Singleton GetInstance { get { return singleInstance; } } }
是不是覺得很優(yōu)雅, 利用靜態(tài)變量去實(shí)現(xiàn)單例, 由CLR保證,在程序第一次使用該類之前被調(diào)用,而且只調(diào)用一次
PS: 但是他的缺點(diǎn)也很明顯, 在程序初始化后, 靜態(tài)對(duì)象就被CLR構(gòu)造了, 哪怕你沒用。
利用靜態(tài)構(gòu)造函數(shù)實(shí)現(xiàn)單例模式
public class SingletonSecond { private static SingletonSecond _SingletonSecond = null; static SingletonSecond() { _SingletonSecond = new SingletonSecond(); } public static SingletonSecond CreateInstance() { return _SingletonSecond; } }
靜態(tài)構(gòu)造函數(shù):只能有一個(gè),無參數(shù)的,程序無法調(diào)用 。
同樣是由CLR保證,在程序第一次使用該類之前被調(diào)用,而且只調(diào)用一次。同靜態(tài)變量一樣, 它會(huì)隨著程序運(yùn)行, 就被實(shí)例化, 同靜態(tài)變量一個(gè)道理。
單例模式中的延遲加載
延遲加載或延遲加載是一種設(shè)計(jì)模式,或者您可以說這是一個(gè)概念,通常用于將對(duì)象的初始化延遲到需要時(shí)。因此,延遲加載的主要目標(biāo)是按需加載對(duì)象,或者您可以根據(jù)需要說出對(duì)象。
作為 .NET Framework 4.0 的一部分引入的惰性關(guān)鍵字為惰性初始化(即按需對(duì)象初始化)提供了內(nèi)置支持。如果要使對(duì)象(如 Singleton)以延遲初始化,則只需將對(duì)象的類型(單例)傳遞給lazy關(guān)鍵字,如下所示。
private static readonly Lazy<Singleton> Instancelock = new Lazy<Singleton>(() => new Singleton());
public sealed class Singleton { private Singleton() {} private static readonly Lazy<Singleton> Instancelock = new Lazy<Singleton>(() => new Singleton()); public static Singleton GetInstance { get { return Instancelock.Value; } } }
到此這篇關(guān)于C#實(shí)現(xiàn)單例模式的多種方式的文章就介紹到這了。希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
在Parallel中使用DbSet.Add()發(fā)現(xiàn)的一系列多線程問題和解決思路詳解
這篇文章主要介紹了在Parallel中使用DbSet.Add()發(fā)現(xiàn)的一系列多線程問題和解決過程的相關(guān)資料,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下2016-11-11C#自動(dòng)創(chuàng)建數(shù)據(jù)庫實(shí)現(xiàn)代碼
C#下創(chuàng)建數(shù)據(jù)庫的代碼2008-03-03c# WPF設(shè)置軟件界面背景為MediaElement并播放視頻
這篇文章主要介紹了c# WPF如何設(shè)置軟件界面背景為MediaElement并播放視頻,幫助大家更好的理解和學(xué)習(xí)使用c#,感興趣的朋友可以了解下2021-03-03c#中的interface abstract與virtual介紹
abstract 與virtual : 方法重寫時(shí)都使用 override 關(guān)鍵字,interface中的方法和abstract方法都要求實(shí)現(xiàn)2013-07-07C#并行編程之?dāng)?shù)據(jù)并行Tasks.Parallel類
這篇文章介紹了C#并行編程之?dāng)?shù)據(jù)并行Tasks.Parallel類,文中通過示例代碼介紹的非常詳細(xì)。對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-05-05