Skip to main content
 首页 » 编程设计

c#之为什么锁定的 Parallel foreach 不会立即死锁

2024年02月25日32jpfss

我注意到我的程序中存在死锁,并且很快找到了原因。我在 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); 
        } 
    } 
} 

输出因运行而异。但很多时候就像 你好 0 你好 4 你好 5 你好 8 你好 9

请您参考如下方法:

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

由于您从 sayHello 获得了一些输出,这意味着 Parallel.For 正在使用当前线程进行某些计算 - 请记住它会划分它处理的调用次数基于您的 CPU 上可用的核心到每个线程 - 那些正在调用 Console.WriteLine 调用。但是在 Parallel.For 完成之前,它正在使用的其他线程无法进入 lock。

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