C#中静态初始化程序的线程安全性

时间:2013-06-26 21:25:29

标签: c# multithreading thread-safety static-initialization

每个人都说静态初始化程序是线程安全的,但我担心一个特定的细节。

假设我有

static class MyStaticClass
{
    public static readonly object myField = MyOtherClass.GetNewObject();
}

static class MyOtherClass
{
    public static object GetNewObject()
    { /* arbitrary code that returns a new object */ }
}

MyStaticClass.myField尚未初始化时,C#保证以下哪一项?

  1. 如果线程1和2尝试一起访问myField(按此顺序),GetNewObject将在线程2读取{{1}之前执行启动 }。

  2. 如果线程1和2尝试一起访问myField(按此顺序),myField将在线程2读取{{1}之前执行已完成 }。

  3. CLR一般情况如何:如果它的保证与C#不同,它们有何不同之处? 在更新版本的.NET框架中是否更改了行为?

    注意:

    这是一个棘手的问题,我认为一个完整的答案可能会提到静态构造函数和静态初始化程序之间的区别,以及它们如何与{{1产生声明的结果。

2 个答案:

答案 0 :(得分:3)

案例2将受到尊重。在初始化类型之前,不能取消引用类字段,属性或方法,并且在静态构造函数完成之前不会初始化类型。据我所知,静态构造函数是阻塞调用。

http://msdn.microsoft.com/en-us/library/aa645612(v=vs.71).aspx

“类的静态构造函数在给定的应用程序域中最多执行一次。”

请参阅Eric Lippert的回复:https://stackoverflow.com/a/9399027/2420979并注意“cctor”是静态构造函数的IL。

  

没有cctors直接或间接调用MyMethod!现在有可能在MyClass的cctor完成之前调用像MyMethod这样的静态方法吗?

没有

  

即使涉及多个线程,这仍然是正确的吗?

是。在任何线程上调用静态方法之前,cctor将在一个线程上完成。

  

可以不止一次调用cctor吗?假设两个线程都导致cctor运行。

无论涉及多少线程,保证最多只调用一次cctor。如果两个线程“同时”调用MyMethod,那么它们就会竞争。其中一个失败了比赛并阻塞,直到MyClass cctor在获胜线程上完成。

答案 1 :(得分:2)

取自MSDN

  

静态成员在第一次访问静态成员之前和静态构造函数(如果有的话)被调用之前被初始化。

如果第二个方法在两个不同的线程中运行但从不使用静态类,则永远不会构建它。但是,如果有引用它,它将在两个线程中的任何一个访问它之前初始化。