在Parallel.For中,是否可以同步每个线程?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了在Parallel.For中,是否可以同步每个线程?相关的知识,希望对你有一定的参考价值。

在Parallel.For中,是否可以使用'WaitAll'同步每个线程?

  Parallel.For(0, maxIter, i =>
  {
            // Do stuffs

           // Synchronisation : wait for all threads => ???

           // Do another stuffs
  });
答案

Parallel.For,在后台,将循环的迭代批处理为一个或多个Tasks,可以并行执行。除非您获得分区的所有权,否则任务(和线程)的数量(并且应该!)将被抽象掉。一旦所有任务完成(即不需要Parallel.For),控制将仅退出WaitAll循环。

当然,这个想法是每个循环迭代都是独立的,不需要同步。

如果在紧密循环中需要同步,那么您没有正确隔离任务,或者这意味着Amdahl's Law生效,并且无法通过并行化加速问题。

但是,对于聚合类型模式,您可能需要在完成每个任务后进行同步 - 使用overloadlocalInit / localFinally来执行此操作,例如:

// allTheStrings is a shared resource which isn't thread safe
var allTheStrings = new List<string>();
Parallel.For(         // for (
  0,                  // var i = 0;
  numberOfIterations, // i < numberOfIterations;
  () => new List<string> (), // localInit - Setup each task. List<string> --> localStrings
  (i, parallelLoopState, localStrings) =>
  {
     // The "tight" loop. If you need to synchronize here, there is no point 
     // using parallel at all
     localStrings.Add(i.ToString());
     return localStrings;
  },
  (localStrings) => // local Finally for each task.
  {
     // Synchronization needed here is needed - run once per task
     lock(allTheStrings)
     {
        allTheStrings.AddRange(localStrings);
     }
  });

在上面的例子中,您也可以将allTheStrings声明为

var allTheStrings = new ConcurrentBag<string>();

在这种情况下,我们不会要求在lock中使用localFinally

另一答案

您不应该(出于其他用户声明的原因),但如果您愿意,可以使用Barrier。这可以用于使所有线程在X个参与者遇到屏障之前在某个点等待(阻塞),导致屏障继续并且线程解除阻塞。正如其他人所说,这种方法的缺点是陷入僵局

以上是关于在Parallel.For中,是否可以同步每个线程?的主要内容,如果未能解决你的问题,请参考以下文章

总结:任务线程和同步

C#之任务,线程和同步

Parallel.For在末尾附近成为单线程

是否可以在 Parallel.For 中定义执行顺序?

Parallel.For(Foreach) 将创建多少个线程?默认 MaxDegreeOfParallelism?

我可以在 Parallel.For 循环中使用相同的函数委托吗