6

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

假设我有

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

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

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

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

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

一般来说,CLR 怎么样:如果它的保证与 C# 的不同,那么它们在哪些方面不同?
.NET 框架的最新版本中的行为是否发生了变化?

笔记:

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

4

2 回答 2

3

案例 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 将在一个线程上完成。

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

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

于 2013-06-26T21:30:30.683 回答
2

取自MSDN

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

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

于 2013-06-26T21:33:26.197 回答