C# 枚举时替换集合

标签 c# multithreading

根据讨论here ,在互联网上的某个地方,已验证在枚举某些类型的集合时替换它们是可能的/线程安全的。

我的下面的测试似乎证实了这一点。

// This test confirmed insufficient by comments
var a = new List<int> { 1, 2, 3 };

Parallel.For(1, 10000, i => {
    foreach (var x in a)
        Console.WriteLine(i + x);
});
Parallel.For(1, 10000, i => a = new List<int> { 1, 2, 3, 4 });

但是,在我开始在代码中实现它之前,我非常想阅读一些官方文档或与此事实相关的一些具体引用资料。

有人可以验证这一点/发布链接吗?

最佳答案

正如已经提到的,你实际上并没有变异 a当你迭代它的时候。你迭代了一堆,然后在完成一堆迭代后,你正在变异 a一堆,因为Parallel.For将阻塞,直到完成所有迭代的执行。

但是,即使你正在变异a与这里的迭代并行,它实际上是完全安全的。 foreach将读取 a 的值从一开始一次,获取对列表的引用,然后从那时起,它永远不会查看 a再次。它将使用本地副本来引用从 a 获得的列表。 ,因此它不会知道或关心对变量 a 进行了哪些更改在那之后。因此,如果您要改变列表 a指向并迭代a同时,你也不知道正在迭代的列表是否是 a 中的列表。在另一个线程中进行更改之前或之后,但您知道正在迭代的列表必须是一个列表或另一个列表,而不是某种错误或两者的混合。

现在,如果您要改变列表 a引用而不是改变变量 a指向一个新的引用,那就完全不同了。 List并非设计为同时从多个线程访问,因此会发生各种不好的事情。如果您使用专门设计用于从多个线程访问的集合,并且按照设计的方式使用它,那么它可以正常运行。

关于C# 枚举时替换集合,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41398708/

相关文章:

c# - 使用 LINQ(夹具列表)形成锦标赛表

c# - 查询azure表服务给出不同的结果

c - 如何使用多线程丢弃 scanf 错误并从 4 个输入整数中识别最高素数

c# - 如何使用 .NET Action 执行参数数量未知的方法?

c# - 如何缩短此 linq to sql 查询?

c# - 多服务日志记录 - 最佳实践

c# - 将 for 循环转换为带索引的 foreach

java - Java并发框架的submit方法

pthreads 程序的竞争条件会使操作系统或 X 完全崩溃吗?

java - 模拟大量用户对 Web 服务的请求的好方法是什么?