我从未使用Parallel.ForEach
,但我玩过它并发现了这种情况。
我运行一个并行循环(msdn https://msdn.microsoft.com/en-us/library/dd997393(v=vs.110).aspx上的代码使用subtotal *=2
编辑它以尝试理解它在做什么),首先使用可枚举范围(0,1)
然后{{ 1}}然后我再次运行第二个但是在线程休眠200毫秒之后,结果则不同
如果(0,1,2)
没有被注释掉,这就是结果
Thread.sleep(200)
如果result 1 = 2
result 2 = 6
result 3 = 4
被注释掉,这就是结果
Thread.sleep(200)
这是代码
result 1 = 2
result 2 = 6
result 3 = 6
我认为它与线程相互作用有关,但这似乎是一个bug
注意我确实看过Simulation gives different result with normal for loop Vs Parallel For
为什么会这样?
答案 0 :(得分:3)
因为这段代码定义不明确:
Parallel.ForEach<int, long>(nums,() => 0,(j, loop, subtotal) =>
{
subtotal += 1;
subtotal *= 2;
return subtotal;
},(finalResult) => Interlocked.Add(ref total, finalResult));
在那里,如果单个线程执行两次迭代,那么你得到结果6.实际上,你做了:
subTotal = 0; //From init
subTotal += 1; //=1 First iteration
subTotal *= 2; //=2 First iteration
subTotal += 1; //=3 Second iteration
subTotal *= 2; //=6 Second iteration
total += subTotal; //=6 End gathering (actually interlocked)
但是如果两个线程共享工作,那么你得到
subTotal1 = 0; //From init
subTotal2 = 0; //From init
subTotal2 += 1; //=1
subTotal1 += 1; //=1
subTotal1 *= 2; //=2
subTotal2 *= 2; //=2
total += subTotal1 //=2 End gathering 1 (interlocked)
total += subTotal2 //=4 End gathering 2 (interlocked)