免费观看又色又爽又黄的小说免费_美女福利视频国产片_亚洲欧美精品_美国一级大黄大色毛片

C#中的單例模式

一般的,設計模式中用到單例模式,代碼通常會如下:

成都一家集口碑和實力的網站建設服務商,擁有專業的企業建站團隊和靠譜的建站技術,10多年企業及個人網站建設經驗 ,為成都1000+客戶提供網頁設計制作,網站開發,企業網站制作建設等服務,包括成都營銷型網站建設,品牌網站制作,同時也為不同行業的客戶提供做網站、成都網站建設的服務,包括成都電商型網站制作建設,裝修行業網站制作建設,傳統機械行業網站建設,傳統農業行業網站制作建設。在成都做網站,選網站制作建設服務商就選創新互聯建站

public sealed class Singleton
{
    private static Singleton instance=null;

    private Singleton()
    {
    }

    public static Singleton Instance
    {
        get
        {
            if (instance==null)
            {
                instance = new Singleton();
            }
            return instance;
        }
    }
}

代碼比較簡單,用到一個公有的靜態屬性和一個私有的靜態字段。并且把構造函數設為私有,防止該類被實例化。

但上述代碼在多線程情況下并不可靠。有一種情況下。2個線程在get的時候,都檢測到instance==null,因此各自創建了一個Singleton對象,破壞了單例的原則。

因此改進后的代碼就是加鎖。

public sealed class Singleton
{
    private static Singleton instance = null;
    private static readonly object padlock = new object();

    Singleton()
    {
    }

    public static Singleton Instance
    {
        get
        {
            lock (padlock)
            {
                if (instance == null)
                {
                    instance = new Singleton();
                }
                return instance;
            }
        }
    }
}

加鎖之后,多線程的操作也變的同步了,同一時間只能有獲得鎖的那個線程才能創建對象。這保證了對象的唯一,但是這個會損耗性能。

因為每次get的時候,都會加鎖,因此可以把代碼修改一下,如果對象已經存在了,就不需要加鎖來創建對象。代碼修改如下:

public sealed class Singleton
{
    private static volatile Singleton instance = null;
    private static readonly object padlock = new object();

    Singleton()
    {
    }

    public static Singleton Instance
    {
        get
        {
            if (instance == null)
            {
                lock (padlock)
                {
                    if (instance == null)
                    {
                        instance = new Singleton();
                    }
                }
            }
            return instance;
        }
    }
}

仔細看一下,就會發現,上述代碼中,有2次檢測instance == null,因此也成為雙重檢測。注意,由于Java中內存模型的問題,上述雙重檢測代碼,對Java不一定有效。

在C#代碼中,考慮下面的場景,有2個線程A,B

1.A線程進入get

2.A線程檢測到instance==null

3.A線程獲得鎖

4.A線程實例化一個對象

5.B線程進入get

6.B線程檢測是否instance==null

問題出現在第4,5,6步驟。

當第4步執行的時候,很有可能出現這種情況,CLR為Singleton對象在托管堆上分配了空間,并且讓instance指向了這個空間,然后再去調用Singleton的構造函數。而漏洞就在這里,線程B可能未等到線程A運行完Singleton的構造函數,就進入get檢測instance!=null,認為對象不是null,然后就直接返回instance,而此時,instance指向的值還在初始化呢,這就可能導致線程B得到的對象是沒完全初始化成功的,可能引起代碼錯誤。當然,這種錯誤的可能性非常少見,但還是會有一定的概率。

因此,上述代碼中instance變量加了一個關鍵字volatile,加它的作用,是為了訪問這個instance的時候,確保instance分配了空間并且初始化完成了(volatile確保該字段在任何時間呈現的都是最新的值)。

如果不使用volatile關鍵字,也可以將instance = new Singleton();語句替換成Interlocked.Exchange(ref instance,new Singleton())。

在C#中,對于實現單例模式,更為推崇的方法是使用靜態變量初始化。

有些設計模式的書中,避免使用靜態初始化的原因之一是C++ 規范在靜態變量的初始化順序方面留下了一些多義性。幸運的是,.NET Framework 通過其變量初始化處理方法解決了這種多義性:

public sealed class Singleton
{
   private static readonly Singleton instance = new Singleton();
   
   private Singleton(){}

   public static Singleton Instance
   {
      get 
      {
         return instance; 
      }
   }
}

CLR保證了靜態字段初始化操作總是線程安全的,無論多少線程同時訪問該類,類中的靜態字段只可能被初始化一次(每個應用程序域)。

這是因為,類中的靜態字段的初始化,是由類的靜態構造函數完成的,C#編譯器檢測到類中有靜態字段后,會為該類生產一個靜態構造函數(可以從IL代碼中看到.cctor方法),也就是說下面代碼是等價的:

class SomeType{
    Static int x = 5;
    }

等價于

class SomeType
{
    Static int x;
    Static SomeType()
    {
        x = 5;
    }
}

因此上述的instance只會初始化一次。保證了單例。這種方法使用了CLR的特性,對于其他語言并不保證,是.NET平臺上推崇的一種實現singleton的方式。

上述實現方法有個不足在于不能延遲加載對象,如果Singleton中還有其他靜態字段,引用該靜態字段的時候,會導致Singleton被創建了。因此,可以在該類中再嵌套一個類來實現延遲加載。如下:

public sealed class Singleton
{
    private Singleton()
    {
    }

    public static Singleton Instance { get { return Nested.instance; } }
        
    private class Nested
    {
        internal static readonly Singleton instance = new Singleton();
    }
}

上述代碼,只有當訪問Instance屬性的時候,才會觸發Nested類的靜態字段,從而初始化一個Singleton對象,因此實現了延遲加載,但是設計比較復雜,不推薦使用。

在.NET4.0中,還有一種更優雅的方法實現延遲加載,即使用Lazy<T>對象。

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

    private Singleton()
    {
    }
}

可以參考之前總結的文章http://cnn237111.blog.51cto.com/2359144/1213187


參考:

http://csharpindepth.com/Articles/General/Singleton.aspx#unsafe

http://msdn.microsoft.com/en-us/library/ff650316.aspx

http://mcwilling.blog.163.com/blog/static/1950971712013357359564/

NET4.0面向對象編程漫談基礎篇.金旭亮

新聞名稱:C#中的單例模式
瀏覽地址:http://m.newbst.com/article2/jeejic.html

成都網站建設公司_創新互聯,為您提供品牌網站制作ChatGPT虛擬主機網站內鏈網站收錄外貿網站建設

廣告

聲明:本網站發布的內容(圖片、視頻和文字)以用戶投稿、用戶轉載內容為主,如果涉及侵權請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網站立場,如需處理請聯系客服。電話:028-86922220;郵箱:631063699@qq.com。內容未經允許不得轉載,或轉載時需注明來源: 創新互聯

成都網站建設