这是我对标准感到困惑的部分:http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-335.pdf#page=178&zoom=auto,87,610%22
2.1。如果类型尚未初始化,请尝试获取初始化锁。
2.2.1。如果未成功,请查看该线程还是等待该线程完成的任何线程已经持有该锁。
2.2.2。如果是这样,则返回,因为阻塞将导致死锁。现在,该线程将看到该类型的未完全初始化状态,但是不会出现死锁。
以下代码在我测试时会死锁,这似乎与标准相矛盾:
public static class Foo {
static Foo() {
var otherThread = new Thread(() => { Thread.Sleep(1000); SomeFunction(); });
otherThread.Start();
otherThread.Join();
}
public static void SomeFunction() {
}
}
class Program {
static void Main() {
Foo.SomeFunction();
}
}
根据标准,我希望发生以下情况:
这是怎么了?
答案 0 :(得分:2)
“等待此线程完成的任何线程”是指等待使用静态线程的初始化锁的所有线程,而不是等待使用任何可能的同步机制的线程。静态初始化机制无法知道其他线程正在使用另一个完全不同的机制在另一个线程上等待。
引用的部分是指以下示例不会死锁的事实:
public class A
{
static A()
{
Thread.Sleep(TimeSpan.FromSeconds(1));
B.DoNothing();
}
public static void DoNothing() { }
}
public class B
{
static B()
{
Thread.Sleep(TimeSpan.FromSeconds(1));
A.DoNothing();
}
public static void DoNothing() { }
}
private static void Main()
{
Task.Run(() => B.DoNothing());
A.DoNothing();
}
此示例不会死锁,因为一个线程正在等待另一个线程释放静态初始值设定项锁定,因此当该线程最终要求原始线程拥有的静态初始值设定项锁定时,带引号的子句就会踢进去,跳过锁。