Moc*_*aiz 0 c# multithreading parallel.foreach
我已经编写了3种不同的计算整数数组之和的方法,但是,我得到了第三种方法的不同结果.
初始化:
int n = 100;
int[] mArray = new int[n];
for (int i = 0; i < mArray.Length; i++)
mArray[i] = 1;
Run Code Online (Sandbox Code Playgroud)
第一:
int sum1 = mArray.Sum();
Console.WriteLine("sum1 " + sum1);
Run Code Online (Sandbox Code Playgroud)
第二:
int sum2 = 0;
for (int i = 0; i < mArray.Length; i++)
sum2 += mArray[i];
Console.WriteLine("sum2 " + sum2);
Run Code Online (Sandbox Code Playgroud)
第三:
int sum3 = 0;
Parallel.ForEach(mArray, item =>
{
sum3 += item;
});
Console.WriteLine("sum3 " + sum3);
Run Code Online (Sandbox Code Playgroud)
显然,3种方法给出了如下所示的相同输出:

然而,当n增加(例如,n = 30000)时,第三种方法给出了令人惊讶的错误结果

注意:我使用ConcurrentBag测试了这些方法,这是一个线程安全的集合.我想,没有溢出问题.代码在Windows 10 x64计算机(Intel核心I-7 @ 3.30ghz)上进行测试
理解为什么Parallel.For的行为不同会很有趣.
问题是sum3您使用时可以通过多个线程访问Parallel.ForEach.sum3 += item;通常会涉及三个操作:1.读取sum3临时存储的值.2.增加该存储的值item; 3.将结果存回sum3.
当同时存在多个线程时,操作很可能会混合.例如,如果您有两个线程A和B,两者都可以读取相同的值sum3,然后进行添加并将新值存储回来.
要解决此问题,您需要保护您的访问权限sum3.代码应该如下所示:
object objLock = new object();
int sum3 = 0;
Parallel.ForEach(mArray, item =>
{
lock (objLock) { sum3 += item; }
});
Console.WriteLine("sum3 " + sum3);
Run Code Online (Sandbox Code Playgroud)
但是,这将完全否定并行执行的效果.