2017-04-16 165 views
0

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

代码:

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; 
     } 
    } 
} 
+1

[线程安全的C#Singleton模式(HTTP的可能重复://计算器。com/questions/12316406/thread-safe-c-sharp-singleton-pattern) – Sanket

+0

如果适用,请考虑使用依赖注入而不是单例。一个容器实例化所有应该有单个对象的类,并通过ctor将它们注入需要它们的类。 Unity是一个在C#中支持这个框架的框架。# – Itsik

回答

0

您在这里使用了什么叫双重检查锁定,对于多线程代码一个相当普遍的系列化格局。有用。

锁,一旦你掉出lock范围被自动释放。

假设存在争用,一个线程会测试 - >获取 - >测试 - >初始化 - >释放,然后下一个测试 - >获取 - >测试 - >释放:没有双重初始化。

0

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

每个线程获取并单独释放锁。第一个线程获取锁定;当它有锁时,第二个线程不能获取它。

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

…并将第二个线程创建新的实例或将它共享第一个线程实例化?

在这个特定的实现中,即使第二个线程最初观察到后台字段为null,该单例也只初始化一次。通过使用lock,代码确保只有一个线程会实际创建单例实例。

有些情况下,可能会出现不止一个初始化的变化,但恕我直言,这些低劣的方式来做到这一点。

这就是说,对于这个问题,这是我的看法是,在.NET的背景下,即使是双锁上面不必要的复杂。在大多数情况下,使用简单的字段初始值设定项即可。如果效率不够高,可以使用Lazy<T>类。

一个更加深入的讨论,请参阅提供有相关的堆栈溢出问题Thread Safe C# Singleton Pattern和引用。

+0

谢谢彼得!!!!!! – Pushkar

1

还有一个最好的方式来实现这一点,我们可以创建一个静态构造函数这将是很好。