为什么一个锁定的并行foreach不会立即死锁?

时间:2018-03-20 08:34:08

标签: c# task task-parallel-library parallel.foreach

我注意到我的程序中的死锁相对很快就找到了原因。我从Parallel.Foreach循环调用了一个锁定的getter。 通常嵌套锁没有问题,同步for循环确实没有死锁。但是为什么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

1 个答案:

答案 0 :(得分:3)

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

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

这就是为什么有些电话会成功的。