并行编程联锁 C#

Posted

技术标签:

【中文标题】并行编程联锁 C#【英文标题】:Parallel Programming Interlocked C# 【发布时间】:2011-11-13 07:51:40 【问题描述】:

我对这个例子感到困惑

http://msdn.microsoft.com/en-us/library/dd997393.aspx

Parallel.ForEach<int, long>(nums, // source collection
                                    () => 0, // method to initialize the local variable
                                    (j, loop, subtotal) => 
                                    
                                        subtotal += nums[j]; 
                                        return subtotal; 
                                    ,

                                    (finalResult) => Interlocked.Add(ref total,finalResult)                                        );

我不知道为什么最后一个代表(finalResult) =&gt; Interlocked.Add(ref total,finalResult) 需要一个 Interlock,而前面的表达式

(j, loop, subtotal) => 
                                    
                                        subtotal += nums[j]; 
                                        return subtotal; 
                                    ,

没有?

谢谢

【问题讨论】:

【参考方案1】:

Parallel.For()Parallel.ForEach() 方法使用了 Partitioner。在 10,000 个单独的任务上执行超过 10,000 个元素的循环是非常低效的。分区器将数据分割成段,理想情况下,ForEach() 将在 4 核 CPU 上的 2,500 个元素的 4 个任务(线程)中执行。这有时需要一些启发式方法,您可以编写自己的自定义分区器。

当使用ForEach() 的“正常”(简单)重载时,这是完全透明的。但是您的示例使用了显示分区的&lt;TLocal&gt; 重载之一。

subtotal += nums[j]; 语句在 1 个分区内迭代,因此是线程安全的。

(finalResult) =&gt; Interlocked.Add(ref total,finalResult)是分区合并的地方,这部分当然不是线程安全的。

【讨论】:

【参考方案2】:

变量subtotal是“本地数据”,只有一个线程可以访问。

另一方面,total 是一个所有线程都可以修改的变量,并且可能有多个线程可能会尝试同时更新总数。

【讨论】:

以上是关于并行编程联锁 C#的主要内容,如果未能解决你的问题,请参考以下文章

C#并发编程之初识并行编程

PLINQ 并行操作Linq

C#并行编程-并发集合

C#并行编程--命令式数据并行(Parallel.Invoke)---与匿名函数一起理解(转载整理)

C#多线程并行编程--第三课

C#并行编程:.NET线程池