繁体   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