簡體   English   中英

為什么單例模式的這種實現可以有兩個實例

[英]Why this realization of Singleton Pattern can have two instances

我正在學習Singleton模式。 在msdn上,單例模式的第一個實現是:

public class Singleton
{
   private static Singleton instance;

   private Singleton() {}

   public static Singleton Instance
   {
      get 
      {
         if (instance == null)
         {
            instance = new Singleton();
         }
         return instance;
      }
   }
 public void Display()
    {
        Console.WriteLine("This is from Singleton!");
    }
}

但是,此實現的主要缺點是它對多線程環境不安全。 如果單獨的執行線程同時輸入Instance屬性方法,則可能會創建Singleton對象的一個​​以上實例。

我試圖創建該類的兩個實例:

Console.WriteLine("First Instance!");
Singleton s = Singleton.Instance;
s.Display();

Console.WriteLine("Second Instance!");
Singleton ss = Singleton.Instance;
ss.Display();

Console.ReadLine();

都創建了“ s”和“ ss”,所以我想我誤會了一些東西。 您能否讓我知道為什么要創建兩個實例?

在這種情況下,您不會創建兩個實例。 而是創建兩個指向同一實例的變量。 第一次調用Singleton s = Singleton.Instance; 創建實例。 第二個調用只返回相同的實例。 如果為單例類提供另一個字段(將其稱為字符串文本),然后調用s.text = "a"; ss.text也將具有值“ a”;

為了使整個線程安全,您可以看一下Mutex類。

在代碼段中,僅當始終由單線程訪問模塊時, if(instance == null)檢查才可以創建類的單個實例。

但是在多線程環境下,它將失敗並導致Singleton類的多個實例。

假設T1和T2是兩個線程,它們正在同時訪問get方法。

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

解釋如下:

  1. 當T1執行if(instance == null) ,如果實例尚未初始化,則進入if塊內部。
  2. 同時,如果T2也執行if(instance == null)行,就在T1進入塊時(T1尚未執行instance = new Singleton()
  3. if阻塞,兩個線程都將被允許進入。
  4. 兩個線程將能夠創建兩個不同的Singleton類實例。

在這里使用多個線程的正確方法如下:

get 
{
    if (instance == null)
    {
        lock();
        if (instance == null)
        {
            instance = new Singleton();
        }
        unlock();
    }
    return instance;
}

兩個(甚至更多個)單獨的線程可以同時進行if (instance == null)檢查。 如果實例尚不存在,則兩個檢查都將返回true 然后,兩個線程將走得更遠,每個線程將創建自己的類實例。

解決方案: 雙重檢查鎖定

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM