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. 如果线程1和2试图一起访问myField(按顺序),则GetNewObject将在线程2读取myField之前启动执行

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

CLR的一般情况如何:如果它的保证与C#的不同,它们在哪些方面不同
在.NET框架的较新版本中,行为是否发生了更改?

注:

这是一个棘手的问题,我认为完整的答案可能会提到静态构造函数和静态initializer之间的区别,以及它们如何与beforefieldinit交互以产生声称的结果。

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

案例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:

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

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