我今天在我的控制台应用程序中运行了一些性能测试,我偶然发现了一些非常意外的事情。我的代码:
int iterations = 1000000;
var mainList = new List<string>();
for (int i = 0; i < iterations; i++)
{
mainList.Add(i.ToString());
}
var listA = new List<string>();
Parallel.ForEach(mainList, (listItem) =>
{
if (Int32.Parse(listItem)%2 == 0)
{
listA.Add(listItem);
}
});
Console.WriteLine("Parallel Count: {0}", listA.Count);
var listB = new List<string>();
foreach (var listItem in mainList)
{
if (Int32.Parse(listItem) % 2 == 0)
{
listB.Add(listItem);
}
}
Console.WriteLine("Sequential Count: {0}", listB.Count);
导致输出:
平行数:495939
顺序计数:500000
我跑了几次,并行循环似乎永远不会在适当的时间执行。任何人都能解释这种“不端行为”吗?并行循环是否值得信赖?
P.S。我知道在提供的代码示例中有很多废话,例如ToString()调用一个整数而不是解析它们但这只是我在测试时提出的随机代码。提前谢谢。
答案 0 :(得分:14)
问题不在于Parallel.ForEach
。您的问题在于List<int>
- 该类不是线程安全的。我的猜测是你遇到了列表对象的线程安全问题。请尝试使用ConcurrentBag<int>
,问题可能会消失。
Microsoft出自thread safety of List<T>
:
要允许多个线程访问集合以进行读写,您必须实现自己的同步。