Ini*_*eer 35 .net c# parallel-processing .net-4.0
我只是在研究新的.NET 4.0功能.有了这个,我正在尝试使用Parallel.For和正常for(x;x;x)循环进行简单的计算.
但是,我有50%的时间得到不同的结果.
long sum = 0;
Parallel.For(1, 10000, y =>
{
sum += y;
}
);
Console.WriteLine(sum.ToString());
sum = 0;
for (int y = 1; y < 10000; y++)
{
sum += y;
}
Console.WriteLine(sum.ToString());
Run Code Online (Sandbox Code Playgroud)
我的猜测是线程正在尝试同时更新"sum".
有明显的方法吗?
Ade*_*ler 69
你不能这样做.sum正在您的并行线程中共享.您需要确保该sum变量一次只能被一个线程访问:
// DON'T DO THIS!
Parallel.For(0, data.Count, i =>
{
Interlocked.Add(ref sum, data[i]);
});
Run Code Online (Sandbox Code Playgroud)
但是......这是一种反模式,因为你已经有效地序列化了循环,因为每个线程都会锁定Interlocked.Add.
您需要做的是添加小计并在最后合并它们,如下所示:
Parallel.For<int>(0, result.Count, () => 0, (i, loop, subtotal) =>
{
subtotal += result[i];
return subtotal;
},
(x) => Interlocked.Add(ref sum, x)
);
Run Code Online (Sandbox Code Playgroud)
您可以在MSDN上找到对此的进一步讨论:http://msdn.microsoft.com/en-us/library/dd460703.aspx
PLUG:您可以在"并行编程指南"的第2章中找到更多相关信息
以下也绝对值得一读......
并行编程模式:使用.NET Framework 4理解和应用并行模式 - Stephen Toub
Blu*_*eft 17
sum += y;实际上是sum = sum + y;.由于以下竞争条件,您得到的结果不正确:
sumsumsum+y1并存储结果sumsum+y2并存储结果sumsum现在等于sum+y2,而不是sum+y1+y2.
你的猜测是正确的.
编写时sum += y,运行时执行以下操作:
y到堆栈如果两个线程同时读取该字段,则第一个线程所做的更改将被第二个线程覆盖.
您需要使用Interlocked.Add,它作为单个原子操作执行添加.