可以通过多个线程访问List <t>吗?</t>

时间:2010-12-21 21:58:35

标签: c# multithreading thread-safety

我打算在多个线程之间共享一个List。该列表将在更改期间锁定,这种更改很少发生。如果同时通过列表从不同的线程进行多次迭代,是否存在线程安全问题?

5 个答案:

答案 0 :(得分:11)

如果可以(如果可以使用.NET 4),请使用BlockingCollection<T>

  

为实现IProducerConsumerCollection<T>的线程安全集合提供阻止和绑定功能。

如果没有,则完全封装列表并添加访问List<T>'s状态的线程安全方法。不要将列表的引用设置为public或从任何方法返回它 - 始终封装引用,以便您可以保证锁定对它的所有访问。

答案 1 :(得分:6)

List<T>不是线程安全的类,但如果每次读/写时都锁定,则不会出现任何问题。根据文件:

  

公共静态(在Visual Basic中共享)   这种类型的成员是线程安全的。   任何实例成员都不是   保证是线程安全的。

     

List<T>可以支持多个读者   同时,只要   集合未被修改。   列举一个集合是   本质上不是线程安全的   程序。在罕见的情况下   枚举与一个或多个竞争   写访问,唯一的方法来确保   线程安全是锁定   整个收集   列举。允许收集   由多个线程访问   读书和写作,你必须   实现自己的同步。

答案 2 :(得分:4)

List<T>通常不是线程安全的。拥有多个阅读器不会导致任何问题,但是,在阅读时您无法写入列表。因此,您需要锁定读取和写入,或者使用类似System.Threading.ReaderWriterLock(允许多个读者但只允许一个编写者)的内容。

答案 3 :(得分:1)

如果那就是你要问的话,它可以同时从多个线程读取。如果是这样,请考虑读写器锁。

答案 4 :(得分:0)

要回答这个问题,您必须先查看文档,然后查看源代码,这里有一个警告 - List<T> 的源代码可以是经过多年的修改。

Darin Dimitrov 引用了 2010 年的文档,与 2021 年有所不同:

<块引用>

这种类型的公共静态(在 Visual Basic 中共享)成员是线程 安全的。不保证任何实例成员都是线程安全的。

对一个 List 执行多次读取操作是安全的,但是 如果在读取集合时修改集合,则可能会出现问题。 为确保线程安全,在读取或写入期间锁定集合 手术。使集合可以被多个线程访问 对于读取和写入,您必须实现自己的同步。 对于具有内置同步的集合,请参阅 System.Collections.Concurrent 命名空间。对于本质上线程安全的 替代方法,请参阅 ImmutableList 类。

如你所见,已经没有这样的句子

<块引用>

枚举集合本质上不是线程安全的 程序

所以建议是 - 检查 List<T>documentationimplementation 并跟踪 .NET 框架上的更改

您的问题的答案是 - 这取决于

如果你使用foreach来遍历列表,那么如果列表被修改了,即使只是调用list[i]=value,其中value等于list[i],你将成为异常,因为 List<T>._version(将由枚举器对象检查)在设置时更改。

for 这个地方的循环不会抛出异常,如果你要修改列表中的一个值,但是改变列表的长度是很危险的。

如果列表在迭代过程中根本不会被修改,那么迭代是线程安全的。