C#中静态初始化程序的线程安全性
本文关键字:线程 安全性 程序 初始化 静态 | 更新日期: 2023-09-27 18:19:59
每个人都说静态初始化程序是线程安全的,但我担心一个特定的细节。
假设我有
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
之前启动执行。如果线程1和2尝试一起访问
myField
(按顺序),则GetNewObject
将在线程2读取myField
之前完成执行。
CLR的一般情况如何:如果它的保证与C#的不同,它们在哪些方面不同
在.NET框架的较新版本中,行为是否发生了更改?
注:
这是一个棘手的问题,我认为完整的答案可能会提到静态构造函数和静态initializer之间的区别,以及它们如何与beforefieldinit
交互以产生声称的结果。
案例2将获得表彰。类字段、属性或方法在初始化类型之前无法取消引用,并且在静态构造函数完成之前不会初始化类型。据我所知,静态构造函数是一个阻塞调用。
http://msdn.microsoft.com/en-us/library/aa645612(v=vs.71).aspx
"类的静态构造函数在给定的应用程序域中最多执行一次。"
请参阅Eric Lippert的回复:https://stackoverflow.com/a/9399027/2420979请注意,"cctor"是静态构造函数的IL。
没有cctor直接或间接调用MyMethod!现在有可能在MyClass的cctor完成之前调用像MyMethod这样的静态方法吗?
没有。
即使涉及多个线程,这仍然是真的吗?
是的。cctor将在一个线程上完成,然后才能在任何线程上调用静态方法。
CCTV可以多次呼叫吗?假设两个线程都导致cctor运行。
无论涉及多少线程,cctor都保证最多被调用一次。如果两个线程"同时"调用MyMethod,那么它们会竞争。其中一人输掉了比赛,并进行了拦网,直到MyClass CCTV在获胜线程上完成。
摘自MSDN:
在第一次访问静态成员之前以及在调用静态构造函数(如果有)之前初始化静态成员。
如果第二个方法在两个不同的线程中运行,但从不使用静态类,则永远不会构建它。但是,如果有对它的引用,它将在两个线程中的任何一个访问它之前被初始化。