为什么Singleton Pattern的这种实现可以有两个实例

时间:2014-08-25 15:05:40

标签: c# design-patterns singleton

我正在学习Singleton Pattern。在msdn上,Singleton Pattern的第一个实现是:

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”都被创建,所以我想我误解了一些东西。 你能告诉我为什么要创建两个实例吗?

3 个答案:

答案 0 :(得分:4)

在这种情况下,您不会创建两个实例。而是创建指向同一实例的两个变量。第一个调用Singleton s = Singleton.Instance;创建实例。第二个调用只返回相同的实例。如果你给singleton类另一个字段(让我们称之为字符串文本)然后调用s.text = "a"; ss.text也会有值" a&#34 ;;

为了使整个事情线程安全,你可以看一下Mutex类。例如。

答案 1 :(得分:2)

在代码段中,只有当单个线程始终访问模块时,if(instance == null)检查才能创建该类的单个实例。

但是在多线程环境的情况下,它将失败并将导致Singleton类的多个实例。

假设T1和T2是两个在某个时刻同时访问get方法的线程。

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

解释如下:

  1. 当T1执行if(instance == null)时,如果实例尚未初始化则输入if if。
  2. 同时,如果T2也执行if(instance == null)行,就在T1进入块时(T1尚未执行instance = new Singleton()
  3. 两个线程都将被允许在if块内。
  4. 两个线程都可以创建两个Singleton Class的差异实例。
  5. 这里使用多个线程的正确方法如下 -

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

答案 2 :(得分:0)

两个(甚至更多)单独的线程可以同时进行if (instance == null)检查。如果实例尚不存在,则两个检查都将返回true。然后两个线程都会更进一步,每个线程都会创建自己的类实例。

解决方案:Double-checked locking

相关问题