随着对多核系统重视的增加,(编程人员)对并行和并发编程的理解显得比从前更加重要。幸运的是,.NET 4 在向开发人员提供的同步原语方面做了很多改进。这些同步原语其中之一就是 Barrier 类(MSDN 中对 Barrier 类的注释:使多个任务能够采用并行方式依据某种算法在多个阶段中协调工作),Emad Omara 正是使用了 Barrier 类实现了并行合并排序。
Emad Omara 的并行合并排序算法假设了在排序操作的过程中(操作者)对计算机的所有 CPU 具有完全的访问权限。虽然这不是必要条件,但只是为了演示。输入数组首先被大致均等地划分为 N 个分区,这里 N 是逻辑 CPU 的数目。每个 CPU 上都会启动一个线程并针对该 CPU 所分配到的(输入数组的)分区进行单线程的排序。
这时所有的线程在继续下一阶段的操作之前都必须同步。半数的线程将会退出同时另一半的线程将会在相邻的分区之间进行合并排序。在之前版本的.NET 框架中,这些操作将会由低层次的 (.NET) 原语或者(编程人员)对 Thread.Join 方法小心谨慎的调用来完成。(而在.NET 4 中) Barrier 类给我们提供了(实现这些操作的)另一种选择。
新的 Barrier 类在某些方面就像 Thread.Join 方法一样,它会等待所有的线程完成(当前阶段)。但它又不像 Thread.Join 方法那样,所有被等待的线程(在完成当前阶段后)需要退出。(在 Barrier 类中)取而代之的,它们仅需要发出已经完成当前阶段的信号并时刻准备着开始下一个阶段。这样就省去了(在不同阶段间)结束和重新创建线程,这些改进对于线程池的操作来说尤其重要。
默认情况下 Barrier 类假设任何一个线程在进行下一阶段的工作前都必须给出前一个阶段的完成信号。很明显这个假设在这里 (Emad Omara 的并行合并排序算法) 不成立,因为每次在进入了合并排序阶段后(计算机)只需要半数(相对于最初建立的线程数)的线程(来完成后续的操作)。因此 Emad 在此调用了 Barrier.RemoveParticipant 方法来把预期将要发出完成信号的线程数量减一。
再次强调这个算法是为了教学目的而设计的,如果要将其运用于产品的构建上那么它还需要进行更多的改进。
查看英文原文: Explaining .NET’s Barrier Class
评论