3

我对这个例子感到困惑

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) => Interlocked.Add(ref total,finalResult) 需要互锁,而前面的表达式

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

才不是?

谢谢

4

2 回答 2

4

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

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

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

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

于 2011-11-13T09:03:54.467 回答
2

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

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

于 2011-11-13T07:55:02.997 回答