【发布时间】:2019-08-07 00:04:44
【问题描述】:
我担心以下两种行为之间的相互作用:
http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-335.pdf#page=179
2.1。如果类型尚未初始化,请尝试获取初始化锁。
2.2.1。如果不成功,查看该线程或等待该线程完成的任何线程是否已经持有锁。
2.2.2。如果是这样,则返回,因为阻塞会造成死锁。该线程现在将看到该类型的未完全初始化状态,但不会出现死锁。
http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-335.pdf#page=69
如果标记为 BeforeFieldInit,则该类型的初始化方法在首次访问为该类型定义的任何静态字段时或之前的某个时间执行。
此代码示例演示了可能的交互:
static class Foo {
public static int A = 1;
}
static class Bar {
public static int B = Foo.A;
}
static class Program {
static void Main() {
Console.WriteLine(Bar.B);
}
}
在任何健全的环境中测试时,它会输出 1。但是,规范似乎允许它输出 0,方法是执行以下操作:
- Main 开始执行。
- Foo 的类型初始化程序开始执行(由于 BeforeFieldInit 规则,此时允许发生这种情况)。
- Bar 的类型初始化程序开始执行(由于 BeforeFieldInit 规则,此时允许发生这种情况)。
- Bar.B 的初始化程序开始执行。
- 请求Foo.A。
- Foo 的类型初始化程序已经在运行,等待它会导致死锁。死锁规则允许我们在未完全初始化的状态下查看 Foo,其中 A 尚未设置为 1,仍具有其默认值 0。
- Bar.B 设置为 0。
- Bar 的类型初始化器已完成。
- Foo.A 设置为 1。
- Foo 的类型初始化程序已完成。
- 主输出 Bar.B,即 0。
这真的允许吗?我应该如何编写类型初始化器,以免被它咬伤?
【问题讨论】:
标签: c# .net deadlock static-initialization static-constructor