C#中静态初始化程序的线程安全性
每个人都说静态初始化程序是线程安全的,但我担心一个特定的细节。
比方说我有
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和2尝试一起访问
myField
(GetNewObject
顺序),则在线程2读取myField
之前,GetNewObject
将开始执行。 -
如果线程1和2尝试一起访问
myField
(GetNewObject
顺序),则在线程2读取myField
之前,GetNewObject
将完成执行。
一般来说CLR怎么样:如果它的保证与C#不同,它们在哪些方面有所不同?
在更新版本的.NET框架中是否更改了行为?
注意:
这是一个棘手的问题,我认为完整的答案可能会提到静态构造函数和静态初始化程序之间的区别,以及它们如何与beforefieldinit
交互以产生声明的结果。
案例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在获胜线程上完成。
摘自MSDN :
静态成员在第一次访问静态成员之前和静态构造函数(如果有的话)被调用之前被初始化。
如果第二个方法在两个不同的线程中运行但从不使用静态类,则永远不会构建它。 但是,如果有对它的引用,它将在两个线程中的任何一个访问它之前进行初始化。