我想知道在多线程的情况下单身如何工作。 假设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;
}
}
}
答案 0 :(得分:1)
实现这一目标的另一种最佳方法是,我们可以创建一个静态构造函数,它会很好。
答案 1 :(得分:0)
您在此处使用的称为双重检查锁定,这是一种用于多线程代码的相当常见的序列化模式。它有效。
一旦您退出lock
范围,就会自动释放锁。
假设存在争用,一个线程将测试 - >获取 - > test-> initialize->释放,而下一个将简单地测试 - >获取 - > test->释放:没有双重-initialization。
答案 2 :(得分:0)
一旦第一个线程完成其操作,第二个线程将进入实例化代码,现在我想知道谁负责释放锁,因为第一个线程已完成其操作
每个线程单独获取和释放锁。第一个线程获取锁;当它有锁时,第二个线程无法获取它。
一旦第一个线程释放了锁(当执行离开由lock
语句控制的代码块时发生),第二个线程就可以获取锁并执行代码。然后,当它完成锁定时,它将再次释放锁定。
...并且第二个线程会创建新实例,还是会共享第一个线程实例化???
在此特定实现中,即使第二个线程最初将后备字段视为null
,单例也只初始化一次。通过使用lock
,代码确保只有一个线程可以实际创建单例实例。
有些变体可能会发生多次初始化,但恕我直言,这些都是较差的方法。
那就是说,就我而言,我认为在.NET的背景下,即使是上面的双锁也是不必要的复杂。在大多数情况下,使用简单的字段初始化程序就足够了。如果效率不高,可以使用Lazy<T>
类。
有关更深入的讨论,请参阅相关的Stack Overflow问题Thread Safe C# Singleton Pattern以及那里提供的参考资料。