为什么锁定的 Parallel foreach 不会立即死锁?

Why does a locked Parallel foreach not deadlock right away?

我注意到我的程序出现了死锁,并且很快就找到了原因。我正在从 Parallel.Foreach 循环中调用锁定的 getter。 一般嵌套锁没问题,一个syncronous for loop确实不会死锁。但是为什么 Parallel.Foreach 循环会死锁,为什么执行次数超过两次?

下面我举个例子

public class Program
{
    public static void Main(string[] args)
    {
       new Test().RunTest();
       Console.WriteLine("Test finished");
    }
}

class Test
{
    object lockObject = new object();
    public void RunTest()
    {
        lock (lockObject)
        {
            Parallel.For(0, 10, sayHello);
        }
    }
    void sayHello(int i)
    {
        lock (lockObject)
        {
            Console.WriteLine("hello " + i);
        }
    }
}

输出与 运行 运行 不同。但很多时候就像 hello 0 hello 4 hello 5 hello 8 hello 9

RunTest中的lock (lockObject)表示只有当前线程可以通过任何和所有后续lock (lockObject),直到代码Parallel.For(0, 10, sayHello)完成。

由于您从 sayHello 获得了一些输出,这意味着 Parallel.For 正在使用当前线程进行某些计算 - 请记住,它根据您的 CPU 上可用的内核 - 那些正在调用 Console.WriteLine 的内核。但是它正在使用的其他线程在 Parallel.For 完成之前无法进入 lock

这就是一些调用成功的原因。