簡體   English   中英

C# 中的靜態構造函數死鎖是否與 ECMA CLI 標准相矛盾?

[英]Do static constructor deadlocks in C# contradict the ECMA CLI standard?

這是我感到困惑的標准部分: 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();
    }
}

根據標准,我預計會發生以下情況:

  1. 主線程獲取 Foo 上的初始化鎖。
  2. 主線程運行 Foo 的靜態構造函數。
  3. 主線程創建 otherThread 並啟動它。
  4. otherThread 開始等待一秒鍾,從而確保第 5 點發生在第 6 點之前。
  5. 主線程開始等待 otherThread 完成。
  6. otherThread 嘗試獲取 Foo 上的初始化鎖,但由於主線程持有該鎖而失敗。
  7. otherThread 放棄執行靜態構造函數,因為主線程持有初始化鎖並等待 otherThread。
  8. otherThread 運行 SomeFunction 並成功完成。
  9. 主線程返回。

這里有什么問題?

“等待此線程完成的任何線程”是指使用靜態線程的初始化鎖等待的任何線程,而不是使用任何可能的同步機制等待的線程。 靜態初始化機制無法知道某個其他線程正在使用另一個線程上的某種完全不同的機制在等待。

引用的部分指的是以下示例不會死鎖的事實:

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();
}

此示例不會死鎖,因為一個線程正在等待另一個線程釋放靜態初始化程序鎖,因此當該線程最終要求原始線程擁有的靜態初始化程序鎖時,引用的子句會啟動,它只是跳過鎖.

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM