单例类C#

时间:2017-04-16 05:59:26

标签: c#

我想知道在多线程的情况下单身如何工作。 假设2个线程进入实例化代码,如下面的代码所示,第一个线程进入实例化代码,它锁定该部分并继续其操作,直到另一个线程等待。 因此,一旦第一个线程完成其操作,第二个线程将进入实例化代码,现在我想知道谁负责释放锁,因为第一个线程已完成其操作,第二个线程将创建新实例或将共享第一个线程实例化???

代码:

public sealed class Singleton
{
    private static Singleton instance = null;
    // adding locking object
    private static readonly object syncRoot = new object();
    private Singleton() { }

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

3 个答案:

答案 0 :(得分:1)

实现这一目标的另一种最佳方法是,我们可以创建一个静态构造函数,它会很好。

答案 1 :(得分:0)

您在此处使用的称为双重检查锁定,这是一种用于多线程代码的相当常见的序列化模式。它有效。

一旦您退出lock范围,就会自动释放锁。

假设存在争用,一个线程将测试 - >获取 - > test-> initialize->释放,而下一个将简单地测试 - >获取 - > test->释放:没有双重-initialization。

答案 2 :(得分:0)

  

一旦第一个线程完成其操作,第二个线程将进入实例化代码,现在我想知道谁负责释放锁,因为第一个线程已完成其操作

每个线程单独获取和释放锁。第一个线程获取锁;当它有锁时,第二个线程无法获取它。

一旦第一个线程释放了锁(当执行离开由lock语句控制的代码块时发生),第二个线程就可以获取锁并执行代码。然后,当它完成锁定时,它将再次释放锁定。

  

...并且第二个线程会创建新实例,还是会共享第一个线程实例化???

在此特定实现中,即使第二个线程最初将后备字段视为null,单例也只初始化一次。通过使用lock,代码确保只有一个线程可以实际创建单例实例。

有些变体可能会发生多次初始化,但恕我直言,这些都是较差的方法。

那就是说,就我而言,我认为在.NET的背景下,即使是上面的双锁也是不必要的复杂。在大多数情况下,使用简单的字段初始化程序就足够了。如果效率不高,可以使用Lazy<T>类。

有关更深入的讨论,请参阅相关的Stack Overflow问题Thread Safe C# Singleton Pattern以及那里提供的参考资料。