换句话说,这个单例实现是线程安全的:
public class Singleton
{
private static Singleton instance;
private Singleton() { }
static Singleton()
{
instance = new Singleton();
}
public static Singleton Instance
{
get { return instance; }
}
}
静态构造函数将在允许任何线程访问该类之前完成运行。
private class InitializerTest
{
static private int _x;
static public string Status()
{
return "_x = " + _x;
}
static InitializerTest()
{
System.Diagnostics.Debug.WriteLine("InitializerTest() starting.");
_x = 1;
Thread.Sleep(3000);
_x = 2;
System.Diagnostics.Debug.WriteLine("InitializerTest() finished.");
}
}
private void ClassInitializerInThread()
{
System.Diagnostics.Debug.WriteLine(Thread.CurrentThread.GetHashCode() + ": ClassInitializerInThread() starting.");
string status = InitializerTest.Status();
System.Diagnostics.Debug.WriteLine(Thread.CurrentThread.GetHashCode() + ": ClassInitializerInThread() status = " + status);
}
private void classInitializerButton_Click(object sender, EventArgs e)
{
new Thread(ClassInitializerInThread).Start();
new Thread(ClassInitializerInThread).Start();
new Thread(ClassInitializerInThread).Start();
}
上面的代码产生下面的结果。
10: ClassInitializerInThread() starting.
11: ClassInitializerInThread() starting.
12: ClassInitializerInThread() starting.
InitializerTest() starting.
InitializerTest() finished.
11: ClassInitializerInThread() status = _x = 2
The thread 0x2650 has exited with code 0 (0x0).
10: ClassInitializerInThread() status = _x = 2
The thread 0x1f50 has exited with code 0 (0x0).
12: ClassInitializerInThread() status = _x = 2
The thread 0x73c has exited with code 0 (0x0).
尽管静态构造函数运行了很长时间,但其他线程会停止并等待。所有线程都读取静态构造函数底部的_x集合的值。
虽然其他答案大多是正确的,但对于静态构造函数还有另一个警告。
根据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,见他的帖子在这里。
虽然所有这些答案都给出了相同的一般答案,但有一个警告。
记住,泛型类的所有潜在派生都被编译为单独的类型。因此,在为泛型类型实现静态构造函数时要谨慎。
class MyObject<T>
{
static MyObject()
{
//this code will get executed for each T.
}
}
编辑:
下面是演示:
static void Main(string[] args)
{
var obj = new Foo<object>();
var obj2 = new Foo<string>();
}
public class Foo<T>
{
static Foo()
{
System.Diagnostics.Debug.WriteLine(String.Format("Hit {0}", typeof(T).ToString()));
}
}
在控制台:
Hit System.Object
Hit System.String