真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

C#項(xiàng)目中實(shí)現(xiàn)單例模式的方法有哪些-創(chuàng)新互聯(lián)

C#項(xiàng)目中實(shí)現(xiàn)單例模式的方法有哪些?很多新手對(duì)此不是很清楚,為了幫助大家解決這個(gè)難題,下面小編將為大家詳細(xì)講解,有這方面需求的人可以來(lái)學(xué)習(xí)下,希望你能有所收獲。

讓客戶滿意是我們工作的目標(biāo),不斷超越客戶的期望值來(lái)自于我們對(duì)這個(gè)行業(yè)的熱愛(ài)。我們立志把好的技術(shù)通過(guò)有效、簡(jiǎn)單的方式提供給客戶,將通過(guò)不懈努力成為客戶在信息化領(lǐng)域值得信任、有價(jià)值的長(zhǎng)期合作伙伴,公司提供的服務(wù)項(xiàng)目有:空間域名、網(wǎng)絡(luò)空間、營(yíng)銷軟件、網(wǎng)站建設(shè)、武昌網(wǎng)站維護(hù)、網(wǎng)站推廣。

介紹

單例模式是軟件工程學(xué)中最富盛名的設(shè)計(jì)模式之一。從本質(zhì)上看,單例模式只允許被其自身實(shí)例化一次,且向外部提供了一個(gè)訪問(wèn)該實(shí)例的接口。通常來(lái)說(shuō),單例對(duì)象進(jìn)行實(shí)例化時(shí)一般不帶參數(shù),因?yàn)槿绻煌膶?shí)例化請(qǐng)求傳遞的參數(shù)不同的話會(huì)導(dǎo)致問(wèn)題的產(chǎn)生。(若多個(gè)請(qǐng)求都是傳遞的同樣的參數(shù)的話,工廠模式更應(yīng)該被考慮)

C#中實(shí)現(xiàn)單例有很多種方法,本文將按順序介紹非線程安全、完全懶漢式、線程安全和低/高性能集中版本。

在所有的實(shí)現(xiàn)版本中,都有以下幾個(gè)共同點(diǎn):

  • 的、私有的且無(wú)參的構(gòu)造函數(shù),這樣不允許外部類進(jìn)行實(shí)例化;

  • 類是密封的,盡管這不是強(qiáng)制的,但是嚴(yán)格來(lái)講從上一點(diǎn)來(lái)看密封類能有助于JIT的優(yōu)化;

  • 一個(gè)靜態(tài)變量應(yīng)該指向類的實(shí)例;

  • 一個(gè)公共的靜態(tài)變量用于獲得這個(gè)類的實(shí)例(如果需要,應(yīng)該創(chuàng)建它);

需要注意的是,本文中所有的例子中都是用一個(gè) public static Instance的變量來(lái)訪問(wèn)單例類實(shí)例,要將其轉(zhuǎn)換成公共函數(shù)是很容易的,但是這樣并不會(huì)帶來(lái)效率和線程安全上的提升。

Version 1 - 非線程安全

/// 
/// Bad code!Do not use! 
/// 
public sealed class Singleton
{
 private static Singleton instance = null;
 private Singleton() { }
 public static Singleton Instance
 {
  get
  {
   if (instance == null)
   {
    instance = new Singleton();
   }
   return instance;
  }
 }
}

該版本在多線程下是不安全的,會(huì)創(chuàng)建多個(gè)實(shí)例,請(qǐng)不要在生產(chǎn)環(huán)境中使用!

因?yàn)槿绻麅蓚€(gè)線程同時(shí)運(yùn)行到if(instance==null)判斷時(shí),就會(huì)創(chuàng)建兩個(gè)實(shí)例,這是違背單例模式的初衷的。實(shí)際上在后面那個(gè)線程進(jìn)行判斷是已經(jīng)生成了一個(gè)實(shí)例,但是對(duì)于不同的線程來(lái)說(shuō)除非進(jìn)行了線程間的通信,否則它是不知道的。

Version 2 - 簡(jiǎn)單的線程安全

public sealed class Singleton2
{
 private static Singleton2 instance = null;
 private static readonly object obj = new object();
 private Singleton2() { }
 public Singleton2 Instance
 {
  get
  {
   lock (obj)
   {
    if (instance == null)
    {
     instance = new Singleton2();
    }
    return instance;
   }
  }
 }
}

該版本是線程安全的。通過(guò)對(duì)一個(gè)過(guò)線程共享的對(duì)象進(jìn)行加鎖操作,保證了在同一時(shí)刻只有一個(gè)線程在執(zhí)行l(wèi)ock{}里的代碼。當(dāng)?shù)谝粋€(gè)線程在進(jìn)行instance判斷或創(chuàng)建時(shí),后續(xù)線程必須等待直到前一線程執(zhí)行完畢,因此保證了只有第一個(gè)線程能夠創(chuàng)建instance實(shí)例。

但不幸的是,因?yàn)槊看螌?duì)instance的請(qǐng)求都會(huì)進(jìn)行l(wèi)ock操作,其性能是不佳的。

需要注意的是,這里使用了一個(gè)private static object變量進(jìn)行鎖定,這是因?yàn)楫?dāng)如果對(duì)一個(gè)外部類可以訪問(wèn)的對(duì)象進(jìn)行鎖定時(shí)會(huì)導(dǎo)致性能低下甚至死鎖。因此通常來(lái)說(shuō)為了保證線程安全,進(jìn)行加鎖的對(duì)象應(yīng)該是private的。

Version 3 - Double-check locking的線程安全

/// 
/// Bad code ! Do not use!
/// 
public sealed class Singleton3
{
 private static Singleton3 instance = null;
 private static object obj = new object();
 private Singleton3() { }
 public static Singleton3 Instance
 {
  get
  {
   if (instance == null)
   {
    lock (obj)
    {
     if (instance == null)
     {
      instance = new Singleton3();
     }
    }
   }
   return instance;
  }
 }
}

該版本中試圖去避免每次訪問(wèn)都進(jìn)行加鎖操作并實(shí)現(xiàn)線程安全。然后,這段代碼對(duì)Java不起作用,因Java的內(nèi)存模型不能保證在構(gòu)造函數(shù)一定在其他對(duì)象引用instance之前完成。還有重要的一點(diǎn),它不如后面的實(shí)現(xiàn)方式。

Version 4 - 不完全懶漢式,但不加鎖的線程安全

public sealed class Singleton4
{
 private static readonly Singleton4 instance = new Singleton4();
 /// 
 /// 顯式的靜態(tài)構(gòu)造函數(shù)用來(lái)告訴C#編譯器在其內(nèi)容實(shí)例化之前不要標(biāo)記其類型
 /// 
 static Singleton4() { }
 private Singleton4() { }
 public static Singleton4 Instance
 {
  get
  {
   return instance;
  }
 }
}

這個(gè)版本是的實(shí)現(xiàn)非常的簡(jiǎn)單,但是卻又是線程安全的。C#的靜態(tài)構(gòu)造函數(shù)只有在當(dāng)其類的實(shí)例被創(chuàng)建或者有靜態(tài)成員被引用時(shí)執(zhí)行,在整個(gè)應(yīng)用程序域中只會(huì)被執(zhí)行一次。使用當(dāng)前方式明顯比前面版本中進(jìn)行額外的判斷要快。

當(dāng)然這個(gè)版本也存在一些瑕疵:

不是真正意義上的懶漢模式(需要的時(shí)候才創(chuàng)建實(shí)例),若單例類還存在其他靜態(tài)成員,當(dāng)其他類第一次引用這些成員時(shí)便會(huì)創(chuàng)建該instance。下個(gè)版本實(shí)現(xiàn)會(huì)修正這個(gè)問(wèn)題;

只有.NET中才具有beforefieldinit特性,即懶漢式實(shí)現(xiàn)。且在.Net 1.1以前的編譯器不支持,不過(guò)這個(gè)現(xiàn)在來(lái)看問(wèn)題不大;

所有版本中,只有這里將instance設(shè)置成了readonly,這不僅保證了代碼的高校且顯得十分短小。

Version 5 - 完全懶漢實(shí)例化

public sealed class Singleton5
{
 private Singleton5() { }
 public static Singleton5 Instance { get { return Nested.instance; } }
 private class Nested
 {
  //Explicit static constructor to tell C# compiler
  //not to mark type as beforefieldinit
  static Nested()
  {
  }
  internal static readonly Singleton5 instance = new Singleton5();
 }
}

該版本看起來(lái)稍微復(fù)雜難懂,其實(shí)只是在寫(xiě)法上實(shí)現(xiàn)了上一版本的瑕疵,通過(guò)內(nèi)嵌類的方式先實(shí)現(xiàn)了只有在真正應(yīng)用Instance時(shí)才進(jìn)行實(shí)例化。其性能表現(xiàn)與上一版本無(wú)異。

Version 6 - 使用.NET 4 Lazy type 特性

public sealed class Singleton6
{
 private static readonly Lazy lazy =
   new Lazy(()=> new Singleton6());
 public static Singleton6 Instance { get { return lazy.Value; } }
 private Singleton6() { }
}

如果你使用的是.NET 4或其以上版本,可以使用System.Lazy type來(lái)實(shí)現(xiàn)完全懶漢式。其代碼看起來(lái)也很簡(jiǎn)潔且性能表現(xiàn)也很好。

性能 VS 懶漢式

一般情況下,我們并不需要實(shí)現(xiàn)完全懶漢式,除非你的構(gòu)造初始化執(zhí)行了某些費(fèi)時(shí)的工作。因此一般的,我們使用顯式的靜態(tài)構(gòu)造函數(shù)就能夠適用。

本文翻譯自Implementing the Singleton Pattern in C#, 作者在文中做了一些循環(huán)測(cè)試,具體的讀者可直接閱讀原文。

Exception

有時(shí)候在進(jìn)行構(gòu)造函數(shù)初始化時(shí)可能 會(huì)拋出異常,但這對(duì)整個(gè)應(yīng)用程序來(lái)說(shuō)不應(yīng)該是致命的,所以可能的情況下,你應(yīng)該自己處理這種異常情況。

看完上述內(nèi)容是否對(duì)您有幫助呢?如果還想對(duì)相關(guān)知識(shí)有進(jìn)一步的了解或閱讀更多相關(guān)文章,請(qǐng)關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道,感謝您對(duì)創(chuàng)新互聯(lián)網(wǎng)站建設(shè)公司,的支持。


本文名稱:C#項(xiàng)目中實(shí)現(xiàn)單例模式的方法有哪些-創(chuàng)新互聯(lián)
網(wǎng)站路徑:http://weahome.cn/article/ddepeg.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部