C# 枚举时替换集合

Gun*_*son 2 c# multithreading

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

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

// 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 });
Run Code Online (Sandbox Code Playgroud)

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

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

Ser*_*rvy 5

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

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

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