如何避免C# Parallel.ForEach的竞态条件

avatar
作者
猴君
阅读量:0

要避免 C# 中的 Parallel.ForEach 竞态条件,您需要确保在并行操作期间对共享资源的访问是线程安全的。这可以通过以下几种方式来实现:

  1. 使用锁(Locks):在执行对共享资源的操作时,使用 lock 语句确保一次只有一个线程可以访问资源。
object lockObject = new object(); Parallel.ForEach(items, item => {     lock (lockObject) {         // 访问共享资源的代码     } }); 
  1. 使用线程安全的数据结构:例如 ConcurrentQueue<T>ConcurrentBag<T>BlockingCollection<T> 等,这些数据结构在内部实现了线程安全机制。
ConcurrentQueue<int> queue = new ConcurrentQueue<int>(); Parallel.ForEach(items, item => {     queue.Enqueue(item); }); 
  1. 使用原子操作:对于简单的数值操作,可以使用 Interlocked 类提供的原子操作方法,如 Interlocked.IncrementInterlocked.Decrement
int counter = 0; Parallel.ForEach(items, item => {     Interlocked.Increment(ref counter); }); 
  1. 使用分区:将数据分成多个部分,每个部分在不同的线程中处理。这样可以减少对共享资源的竞争。
int numOfPartitions = Environment.ProcessorCount; var partitions = Partitioner.Create(items, numOfPartitions); Parallel.ForEach(partitions, partition => {     foreach (var item in partition) {         // 处理每个分区的代码     } }); 
  1. 避免全局状态:尽量减少全局状态的使用,因为它可能导致竞态条件。如果必须使用全局状态,请确保对其访问进行同步。

  2. 使用 Parallel LINQ (PLINQ):PLINQ 可以让您以声明式方式编写并行代码,它会自动处理并行性和对共享资源的访问。

var result = items.AsParallel().Where(item => {     // 过滤条件 }).ToList(); 

总之,要避免 Parallel.ForEach 的竞态条件,关键是确保对共享资源的访问是线程安全的。您可以使用锁、线程安全的数据结构、原子操作、分区等方法来实现这一目标。

广告一刻

为您即时展示最新活动产品广告消息,让您随时掌握产品活动新动态!