换句话说,这个单例实现是线程安全的:
public class Singleton
{
private static Singleton instance;
private Singleton() { }
static Singleton()
{
instance = new Singleton();
}
public static Singleton Instance
{
get { return instance; }
}
}
虽然其他答案大多是正确的,但对于静态构造函数还有另一个警告。
根据ECMA-335通用语言的第二节10.5.3.3竞赛和死锁
基础设施
类型初始化本身不会产生死锁,除非有一些代码
从类型初始化器(直接或间接)显式调用
调用阻塞操作。
下面的代码导致死锁
using System.Threading;
class MyClass
{
static void Main() { /* Won’t run... the static constructor deadlocks */ }
static MyClass()
{
Thread thread = new Thread(arg => { });
thread.Start();
thread.Join();
}
}
原作者是Igor Ostrovsky,见他的帖子在这里。
在创建类的任何实例或访问任何静态成员之前,每个应用程序域保证只运行一次静态构造函数。https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/static-constructors
所示的实现对于初始构造是线程安全的,也就是说,构造Singleton对象不需要锁定或空测试。然而,这并不意味着对实例的任何使用都将同步。有很多种方法可以做到这一点;我在下面展示了一个。
public class Singleton
{
private static Singleton instance;
// Added a static mutex for synchronising use of instance.
private static System.Threading.Mutex mutex;
private Singleton() { }
static Singleton()
{
instance = new Singleton();
mutex = new System.Threading.Mutex();
}
public static Singleton Acquire()
{
mutex.WaitOne();
return instance;
}
// Each call to Acquire() requires a call to Release()
public static void Release()
{
mutex.ReleaseMutex();
}
}
虽然其他答案大多是正确的,但对于静态构造函数还有另一个警告。
根据ECMA-335通用语言的第二节10.5.3.3竞赛和死锁
基础设施
类型初始化本身不会产生死锁,除非有一些代码
从类型初始化器(直接或间接)显式调用
调用阻塞操作。
下面的代码导致死锁
using System.Threading;
class MyClass
{
static void Main() { /* Won’t run... the static constructor deadlocks */ }
static MyClass()
{
Thread thread = new Thread(arg => { });
thread.Start();
thread.Join();
}
}
原作者是Igor Ostrovsky,见他的帖子在这里。