c# - 线程安全C#单例模式




design-patterns singleton (7)

懒惰的版本:

public sealed class Singleton
{
    static readonly Lazy<Singleton> lazy = new Lazy<Singleton>(() => new Singleton());
    private Singleton() { }

    public static Singleton Instance => lazy.Value;
}

需要.NET 4和C#6.0(VS2015)或更高版本。

我对这里记录的单例模式有一些疑问: http://msdn.microsoft.com/en-us/library/ff650316.aspxhttp://msdn.microsoft.com/en-us/library/ff650316.aspx

以下代码是文章摘录:

using System;

public sealed class Singleton
{
   private static volatile Singleton instance;
   private static object syncRoot = new object();

   private Singleton() {}

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

         return instance;
      }
   }
}

具体来说,在上面的例子中,是否需要在锁之前和之后将实例与null进行两次比较? 这有必要吗? 为什么不先执行锁定并进行比较?

简化以下是否有问题?

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

         return instance;
      }
   }

表演锁是否昂贵?


你可以急切地创建一个线程安全的Singleton实例,这取决于你的应用程序需求,这是简洁的代码,虽然我更喜欢@andasa的懒惰版本。

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

    private Singleton() { }

    public static Singleton Instance()
    {
        return instance;
    }
}

在几乎所有情况下(即:除了第一个以外的所有情况), instance都不会为空。 获取锁比简单检查更昂贵,因此在锁定之前检查instance的值是一个很好的免费优化。

此模式称为双重检查锁定: http//en.wikipedia.org/wiki/Double-checked_locking


杰弗里里希特建议如下:



    public sealed class Singleton
    {
        private static readonly Object s_lock = new Object();
        private static Singleton instance = null;

        private Singleton()
        {
        }

        public static Singleton Instance
        {
            get
            {
                if(instance != null) return instance;
                Monitor.Enter(s_lock);
                Singleton temp = new Singleton();
                Interlocked.Exchange(ref instance, temp);
                Monitor.Exit(s_lock);
                return instance;
            }
        }
    }


与简单的指针检查instance != null相比,执行锁定非常昂贵instance != null

您在此处看到的模式称为双重检查锁定 。 其目的是避免昂贵的锁定操作,这只需要一次(当首次访问单例时)。 实现是这样的,因为它还必须确保在初始化单例时不会出现线程争用条件导致的错误。

可以这样想:只有当答案为“是,对象已经构建”时,才能保证只有裸检查(没有lock )才能给出正确的可用答案。 但如果答案是“尚未构建”,那么你没有足够的信息,因为你真正想知道的是“它还没有构建,没有其他线程打算很快构建它 ”。 因此,您使用外部检查作为一个非常快速的初始测试,并且只有在答案为“否”时才启动正确的,无错误但“昂贵”的程序(锁定然后检查)。

对于大多数情况,上面的实现已经足够了,但是在这一点上,最好去阅读csharpindepth.com/Articles/General/Singleton.aspxcsharpindepth.com/Articles/General/Singleton.aspx该文章还评估了其他选择。


原因是表现。 如果instance != null (除了第一次以外总是如此),则不需要进行昂贵的lock :同时访问初始化单例的两个线程将不必要地同步。


C#版本历史:

C#是Microsoft开发的一种简单而强大的面向对象编程语言。

自2002年首次发布以来,C#已经发展很多。随着.NET Framework 1.0引入了C#。

下表列出了每个C#版本中引入的重要功能。

最新版本的C#可以在C#版本中使用







c# design-patterns singleton