Parallel.ForeachAsync 时需要互斥体吗?

问题描述 投票:0回答:3

根据我的理解,Parallel.ForeachAsync 调用中的委托会同时执行多次。

如果该委托操作的变量不是该委托的本地变量怎么办?

假设我在委托中增加了一个静态计数器。我需要通过互斥锁或其他东西来保护计数器吗?

c# asynchronous concurrency mutex parallel.foreachasync
3个回答
4
投票

Parallel
不是魔法。您需要使用所有常用机制来防止访问共享状态和最坏情况,如果无法避免,请同步它。

当然,如果你只是在

Parallel
中进行同步,你很快就会发现它完全毫无价值,以占用更多 CPU 为代价,只能给你带来更好的结果(甚至更糟)。这个想法是将工作分解为互不影响的工作 - 例如,通过确保您正在操作的集合已经拥有它所需的所有输入,并且只将输出生成到输出集合中。然后
Parallel
可以尽最大努力提高效率。但当然,只有当批次足够大以支付同步成本时,它才有效。

请记住,

Parallel
有很多小怪癖,因此请进行概要分析、阅读并非常小心地了解正在发生的事情。这不是魔法。


2
投票

Parallel
并行执行多项工作。如果工作共享非线程安全资源,则该资源可能会被损坏。那么资源需要被保护。

示例:

var values = Enumerable.Range(0, 1000);
int counter = 0;
int safeCounter = 0;

await Parallel.ForEachAsync(values, async (value, token) =>
{
    await Task.Yield(); // Simulate some work
    counter++;
    Interlocked.Increment(ref safeCounter);
});

Console.WriteLine(counter);     // 991  (can vary)
Console.WriteLine(safeCounter); // 1000 (as expected)

1
投票

假设我在委托中增加了一个静态计数器。我需要通过互斥锁或其他东西来保护计数器吗?

是的,你必须使用一些同步机制来保护你的非线程安全共享状态,比如

lock
body
委托在
ThreadPool
上调用,并遵守
MaxDegreeOfParallelism
政策。
Parallel.ForEachAsync
的设计并非只考虑异步并发,而没有并行性。为了防止并行性而又不无意中阻止并发性,您必须跨过困境

© www.soinside.com 2019 - 2024. All rights reserved.