Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/261.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 可以列出一个列表<;t>;被多个线程访问?_C#_Multithreading_Thread Safety - Fatal编程技术网

C# 可以列出一个列表<;t>;被多个线程访问?

C# 可以列出一个列表<;t>;被多个线程访问?,c#,multithreading,thread-safety,C#,Multithreading,Thread Safety,我计划在多个线程之间共享一个列表。在更改期间,列表将被锁定,这种更改很少发生。如果不同线程同时通过列表进行多次迭代,是否存在线程安全问题?如果可以(如果可以使用.NET 4),请使用: 为实现IProducerConsumerCollection的线程安全集合提供阻止和绑定功能 如果没有,则完全封装列表,并添加访问列表状态的线程安全方法。不要将对列表的引用公开或从任何方法返回它-始终封装引用,这样可以保证锁定对它的所有访问。A不是线程安全类,但如果每次读/写时都锁定,则不会出现任何问题。根据文件

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

如果可以(如果可以使用.NET 4),请使用:

为实现
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
的行为与<