C# 可以列出一个列表<;t>;被多个线程访问?
我计划在多个线程之间共享一个列表。在更改期间,列表将被锁定,这种更改很少发生。如果不同线程同时通过列表进行多次迭代,是否存在线程安全问题?如果可以(如果可以使用.NET 4),请使用: 为实现C# 可以列出一个列表<;t>;被多个线程访问?,c#,multithreading,thread-safety,C#,Multithreading,Thread Safety,我计划在多个线程之间共享一个列表。在更改期间,列表将被锁定,这种更改很少发生。如果不同线程同时通过列表进行多次迭代,是否存在线程安全问题?如果可以(如果可以使用.NET 4),请使用: 为实现IProducerConsumerCollection的线程安全集合提供阻止和绑定功能 如果没有,则完全封装列表,并添加访问列表状态的线程安全方法。不要将对列表的引用公开或从任何方法返回它-始终封装引用,这样可以保证锁定对它的所有访问。A不是线程安全类,但如果每次读/写时都锁定,则不会出现任何问题。根据文件
IProducerConsumerCollection
的线程安全集合提供阻止和绑定功能
如果没有,则完全封装列表,并添加访问列表
状态的线程安全方法。不要将对列表的引用公开或从任何方法返回它-始终封装引用,这样可以保证锁定对它的所有访问。A不是线程安全类,但如果每次读/写时都锁定,则不会出现任何问题。根据文件:
公共静态(在Visual Basic中共享)
此类型的成员是线程安全的。
任何实例成员都不是
保证线程安全
列表可以支持多个读卡器
同时,只要
集合未被修改。
在集合中枚举是不正确的
本质上不是线程安全的
程序在罕见的情况下
枚举与一个或多个
写访问,这是确保
螺纹的安全性在于锁紧螺纹
在整个过程中收集
枚举。允许收集
要由多个线程访问的
阅读和写作,你必须
实现您自己的同步
它可以同时从多个线程读取,如果这是您所要求的。如果是这样的话,请考虑读写器锁。 <代码>列表< /> >通常不是线程安全的。拥有多个读卡器不会导致任何问题,但是,您不能在读取列表时写入列表。因此,您需要同时锁定读和写,或者使用类似于System.Threading.ReaderWriterLock的东西(它允许多个读卡器,但只允许一个写卡器)。要回答这个问题,您必须先看一下文档,然后转到源代码,这里有一个警告,列表
的源代码可以多年修改
Darin Dimitrov引用了2010年的文件,与2021年有所不同:
此类型的公共静态(在Visual Basic中共享)成员是线程
安全的。任何实例成员都不能保证线程安全
对一个列表执行多个读取操作是安全的,但是
如果在读取集合时对其进行修改,则可能会出现问题。
为确保线程安全,请在读取或写入期间锁定集合
活动使集合能够由多个线程访问
对于读写,您必须实现自己的同步。
有关内置同步的集合,请参见中的类
System.Collections.Concurrent命名空间。对于固有的线程安全性
或者,请参见ImmutableList类
正如你所看到的,已经没有这样的句子了
通过集合枚举本质上不是线程安全的
程序
因此,建议-检查列表的and,并跟踪.NET framework上的更改
你问题的答案是-视情况而定
如果您使用foreach
遍历列表,那么如果列表被修改,甚至只需调用list[i]=value
,其中value
等于list[i]
,您将成为一个例外,因为列表的版本(将由枚举器对象检查)在设置时被更改
for
如果要修改列表中的值,则此处的循环不会引发异常,但更改列表长度可能会很危险
如果列表在迭代过程中根本不被修改,那么迭代是线程安全的。如果列表被正确锁定,那么可能会出现什么问题?不能锁定列表,只能阻止代码。让所有访问列表(或其元素对象)的代码输入一个lock语句,该语句使用私有对象来保持锁定状态。使用BlockingCollection是否有成本?@Behrooz:成本不超过实现相同锁定逻辑的list
周围的自定义包装器。至于它到底给列表增加了多少开销,我不能说。我很惊讶这个答案被接受了。BlockingCollection
的默认行为是队列而不是列表。无法通过索引访问它,也无法在不删除项的情况下对其进行迭代。我想OP真的需要一个队列。默认id队列,但您可以用任何您想要的来替换它。几乎没有任何情况比ReaderWriterLockSlim
更喜欢ReaderWriterLockSlim
。Slim
版本性能更好,API也更好。没错,但是ReaderWriterLockSlim
仅在v3.5+版本中可用,因为它在System.Core.dll
中ReaderWriterLock
可从v1.1+中获得,并位于mscorlib
中。不幸的是,我不得不使用大量的.Net 2.0代码,因此在这件事上我别无选择。我相信他们删除“通过集合枚举本质上不是线程安全过程”语句的原因是因为它被不可变集合的存在所驳斥。自从Darin Dimitrov的2010年以来,“列表
类型本身实际上没有任何变化。@TheodorZoulias在实现中搜索二进制兼容性。targetSatelist_Desktop_V4_5
这表明ForEach
方法与.NET 4.5之前的标准ForEach
枚举不一致,他们通过使ForEach
的行为与<