我有 C# .NET 4 代码,它添加到
List<string>
内的 Parallel.For
。
我找不到这是否是线程安全的明确答案。
如果不安全,有什么替代方案?
static List<int> Calculate(List<string[]> numbers)
{
List<int> sums = new List<int>();
Parallel.ForEach(numbers,
(nums) =>
{
int sum = 0;
for (int i = 0; i < nums.Length; i++)
sum += Convert.ToInt32( nums[i]);
// is this thread safe or not???
sums.Add(sum);
});
sums.Sort();
return sums;
}
ConcurrentBag<T>
类,一个线程安全的无序集合。有关更多信息和其他线程安全集合,请参阅MSDN 的线程安全集合文档。例如
static List<int> Calculate(List<string[]> numbers)
{
var sums = new ConcurrentBag<int>();
Parallel.ForEach(numbers,
(nums) =>
{
int sum = 0;
for (int i = 0; i < nums.Length; i++)
sum += Convert.ToInt32( nums[i]);
sums.Add(sum);
});
var sorted = sums.OrderBy(x => x).ToList();
return sorted;
}
不,不是。
一个List可以同时支持多个读者,只要 集合未修改。通过集合进行枚举是 本质上不是线程安全的过程。在极少数情况下, 枚举与一个或多个写访问竞争,这是唯一的方法 确保线程安全就是在整个过程中锁定集合 枚举。允许多个集合访问 用于读取和写入的线程,您必须实现自己的 同步。
来自 MSDN
您可以通过将方法转换为 PLINQ 操作来避免线程安全问题(并提高性能):
static List<int> Calculate(List<string[]> numbers)
{
return numbers.AsParallel()
.Select(nums => nums.Sum(Convert.ToInt32))
.OrderBy(i => i)
.ToList();
}