你能解释一下为什么这段代码会死锁吗?
int[] testlist = new int[ ] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
lock ( testlock ) {
Parallel.ForEach( testlist, new ParallelOptions( ) { MaxDegreeOfParallelism = 90 }, ( int i ) => {
Console.WriteLine( "hi there before " + i + " " + Monitor.IsEntered( testlock ) );
lock ( testlock ) {
Console.WriteLine( "hi there inner " + i + " " + Monitor.IsEntered( testlock ) );
}
Console.WriteLine( "hi there after " + i + " " + Monitor.IsEntered( testlock ) );
} );
}
当然没有周围锁这段代码不会死锁。
编辑:
感谢您的解释。典型的输出是:
hi there before 3 True
hi there inner 3 True
hi there after 3 True
hi there before 4 True
hi there inner 4 True
hi there after 4 True
hi there before 5 True
hi there inner 5 True
hi there after 5 True
hi there before 6 True
hi there inner 6 True
hi there after 6 True
hi there before 7 True
hi there inner 7 True
hi there after 7 True
hi there before 8 True
hi there inner 8 True
hi there after 8 True
hi there before 9 True
hi there inner 9 True
hi there after 9 True
hi there before 10 True
hi there inner 10 True
hi there after 10 True
事实上,典型的执行涉及我机器上的两个线程:一个被阻塞等待锁定(“1”那个),另一个正在运行其他迭代(从 3 到 10,注意输出的线性)。 “1”线程永远等待。现在清楚了,谢谢!
请您参考如下方法:
这行不通,因为您肯定会在这里造成死锁:
外层lock(testlock)锁定 testlock然后是 Parallel.ForEach开始处理您的 testlist在多个线程中。现在这些线程到达内部 lock(testlock) , 但由于它仍然被其线程中的外部锁定,因此无法再次锁定它 => 外部 lock直到处理完成才释放,但是直到外部处理才能完成 lock发布 -> 死锁...
您可以使用 MaxDegreeOfParallelism = 1 轻松验证这一点: 然后一切都在主线程中运行,级联锁不会死锁,因为它可以再次锁定,因为它是同一个线程。
你想做什么 - 如果你解释一下,我们可以帮忙吗?
注意:
如果您的系统没有 90! CPU,使用 MaxDegreeOfParallelism = 90 对性能没有帮助。 - 建议使该数字小于或等于您的 CPU/核心数(您可以通过 Environment.ProcessorCount 获得)。
