简体   繁体   English

这两个Singleton实现之间的区别

[英]Difference between these two Singleton implementations

I am learning how to implement some basic design patterns. 我正在学习如何实现一些基本的设计模式。 Whilst learning the Singleton pattern I have noticed that there are two common implementations on the web: 在学习Singleton模式的同时,我注意到Web上有两种常见的实现:

// Possibly from: http://www.yoda.arachsys.com/csharp/singleton.html
// I cannot remember exact source, sorry :(

public sealed class Singleton
{
    // Static members are 'eagerly initialized', that is,
    // immediately when class is loaded for the first time.
    // .NET guarantees thread safety for static initialization
    private static readonly Singleton instance = new Singleton();

    // Private constructor prevents instantiation from other classes
    private Singleton() { }

    // Explicit static constructor to tell C# compiler
    // not to mark type as beforefieldinit
    public static Singleton() { }

    // Get the instance of the singleton
    public static Singleton getInstance()
    {
            return instance;
    }

}

and: 和:

public class Singleton
{
  // Static, VOLATILE variable to store single instance
  private static volatile Singleton m_instance;

  // Static synchronization root object, for locking
  private static object m_syncRoot = new object();

  // Property to retrieve the only instance of the Singleton
  public static Singleton Instance
   {
      get
      {
          // Check that the instance is null
          if (m_instance == null)
          {
              // Lock the object
              lock (m_syncRoot)
              {
                  // Check to make sure its null
                  if (m_instance == null)
                  {
                      m_instance = new Singleton();
                  }
              }
          }

          // Return the non-null instance of Singleton
          return m_instance;
      }
  }
} 
  1. In what scenario would you opt to have eagerly initialized vs lazy initialized? 在什么情况下你会选择急切地初始化vs lazy初始化?
  2. Is the comment in the first example correct in saying that the initialization is thread safe? 第一个例子中的注释是否正确,说初始化是线程安全的? (I know it says it is, but it's the internet...) (我知道它说的是,但它是互联网...)

I definitely would go with your first implementation... 我绝对会选择你的第一个......

the second seems questionable to me... if you need/want a lazy implementation you could use Lazy<T> for that - since it is part of the framework it feels much more comfortable.. 第二个对我来说似乎有问题...如果你需要/想要一个懒惰的实现,你可以使用Lazy<T> - 因为它是框架的一部分,感觉更舒服..

BTW: There are even more ways to implement the Singleton pattern... here is an excellent article . 顺便说一下:有更多的方法来实现Singleton模式...... 这是一篇很棒的文章

I'm not sure but it looks like you got those examples from here: http://www.yoda.arachsys.com/csharp/singleton.html 我不确定,但看起来你从这里得到了这些例子: http//www.yoda.arachsys.com/csharp/singleton.html

If not, read through it. 如果没有,请仔细阅读。 There are a couple of thoughts on the two versions. 关于这两个版本有几点想法。 If you ask me personally: I would go for the 2nd solution if I needed to know if the singleton has already been initialized or not. 如果你个人问我:如果我需要知道单身是否已经初始化,我会选择第二个解决方案。

If you don't have to deal with multithreading, I would use an even simpler approach (see the "Bad Code" examples in the references link). 如果您不必处理多线程,我会使用更简单的方法(请参阅参考链接中的“错误代码”示例)。

The first one is safe and lazy. 第一个是安全和懒惰的。

static constructor s are guaranteed to be executed only once, and immediately before the first access to Instrance . 保证static constructor只执行一次,并且在第一次访问Instrance之前立即执行。 If there is a static constructor(even if empty) then static field initializations are guaranteed to execute directly before the static constructor. 如果存在静态构造函数(即使为空),则保证静态字段初始化直接在静态构造函数之前执行。 If there is no static constructor, field initialization may occur earlier. 如果没有静态构造函数,则字段初始化可能更早发生。


The second one is lazy, but I'm not sure if the double-lock pattern is valid like this. 第二个是懒惰的,但我不确定双锁模式是否有效。 I suspect that it is broken, at least in the ECMA memory model. 我怀疑它已经坏了,至少在ECMA内存模型中是这样。


Personally I'd avoid any Class.Instance singleton pattern in favour of IoC singletons in most situations. 就个人而言,在大多数情况下,我会避免使用任何Class.Instance单例模式来支持IoC单例。

1) that's entirely a design choice. 1)这完全是一种设计选择。 Init up front or init when required. 在需要时预先启动或初始化。

2) Yes, it is thread safe as the CLR guarantees single threaded object initialisation. 2)是的,它是线程安全的,因为CLR保证单线程对象初始化。 (static and instance) (静态和实例)

EDIT 编辑

personally, in the first example, I make the Instance field public and dispense with the getter. 就个人而言,在第一个例子中,我将Instance字段公之于众,并免除了getter。 Be interested to know if there is any reason that this is a bad idea? 有兴趣知道这是不是一个坏主意?

It's a singleton so I'd go for option 1, unless it's a massive object that's not always even needed. 这是一个单身人士所以我会选择第一选项,除非它是一个并不总是需要的大型物体。 But I probably would not make a singleton for something that's often not used at all. 但我可能不会为那些通常根本没用过的东西做单身。

Both implementations are fine, so it depends on what you need. 两种实现都很好,所以它取决于你需要什么。

If performance is not an issue, use the eagerly created instance of the first one. 如果性能不是问题,请使用第一个的热切创建的实例。 Otherwise, use the second one, in which only the first access is synchronized. 否则,使用第二个,其中仅同步第一个访问。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM