只读静态字段初始化的线程安全问题

24
如果创建只读的静态成员,可以这样做:
public sealed class MyClass
{
    public readonly static MyClass Instance = new MyClass();
}
我们知道,如果某个线程第一次访问MyClass,则静态构造函数将初始化MyClass.Instance字段。 但是,如果多个线程同时访问MyClass(即静态字段的初始化是否线程安全),那么是否会创建一个单独的实例(在这种情况下为MyClass)?
答案:是,静态字段的初始化是线程安全的,会创建一个单独的实例。

你只会有一个实例,但它不是线程安全的。你必须实现对它的访问控制(使用Mutex或其他方式)。 - Andre Calil
4
我知道类的实例成员仍然需要线程安全,我的问题是只读静态字段的初始化是否线程安全(即静态构造函数只会被一个线程调用吗?) - Francois Nel
1
它将被运行时仅调用一次。就像您对整个应用程序拥有一个单例 - Andre Calil
3
每个 AppDomain 将有一个 MyClass 的实例。 - João Angelo
2个回答

30

.NET CLR 确保静态初始化始终是线程安全的。无论有多少个线程访问它,并且以什么顺序访问,它始终只会被初始化一次。

您的代码似乎显示出单例模式的开始迹象。
基本上,如果您想在初始化类之前运行自定义代码,则需要自己确保线程安全性。
这是一个示例,您需要使自己的自定义代码线程安全。但静态初始化部分始终是线程安全的。


“.NET CLR 确保静态初始化始终是线程安全的。” 这是正确的,除非有人试图做一些非常奇怪的事情。就像这段代码会导致死锁一样:using System.Threading; class Foo { static void Main() { } static Foo() { Thread thread = new Thread(arg => { }); thread.Start(); thread.Join(); } } - oleksii
另一个例外情况是将静态成员标记为ThreadStatic。 - Tarec

10

我还在努力寻找它...找到了,已添加到答案中。 - David M
链接已失效 @davidm - Chase Florell

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接