Parallel-For循环给出与单循环不同的和结果。我错过了什么?

时间:2016-01-13 06:33:19

标签: multithreading c#-4.0 task-parallel-library parallel-for

我们的一个程序中有一个模糊的错误。我已经将其中的至少一部分缩小到这个并行for循环。

我是一个int [],用于测试目的,填充0到99999。 runningTotal很长。 lockObject是一个新的Object();

Parallel-For循环似乎总是在完成时返回总计704,982,704;单线程循环返回4,999,950,000。

显然是一个线程问题,但我只是没有看到错误。 Parallel-For循环是否正确实现?

以下相关代码:

//i int[] test ---------------------------------------------
object lockObject = new object();
int[] i = new int[100000];
for (int x = 0; x < i.Length; x++)
{
    i[x] = x;
}
long runningTotal = 0;

Parallel.For(0, i.Length,
() => 0,
(x, loopState, subtotal) =>
{
    subtotal += i[x];
    return subtotal;
},
(s) =>
{
    lock (lockObject)
    {
        runningTotal += s;
    }
}
);
runningTotal = 0;
for (int x = 0; x < i.Length; x++)
{
    runningTotal += i[x];
}

1 个答案:

答案 0 :(得分:2)

根本原因是本地状态被声明为int,有时会溢出。

这种情况间歇性地发生,并且与Parallel.For抛出手头任务的工作线程数有关。如果将MaxDegreeOfParallelism限制为1,则可以可靠地发生溢出。

修复方法是将本地状态声明为long

Parallel.For(0, i.Length, () => 0L, ...)

...然后溢出永远不会发生。除此之外,你的逻辑没有任何问题。