我不太确定,所以想询问一下。从一个System.Collections.Generic.List<>
对象中移除和添加项目是否是非线程安全的?
我的情况:
当连接被接收时,它会被添加到列表中,但与此同时,有一个工作程序会删除死掉的连接等。
这样会有问题吗?需要使用lock
吗?
我还想知道是否可以在列表对象上使用锁定及其Foreach<>
方法。
我不太确定,所以想询问一下。从一个System.Collections.Generic.List<>
对象中移除和添加项目是否是非线程安全的?
我的情况:
当连接被接收时,它会被添加到列表中,但与此同时,有一个工作程序会删除死掉的连接等。
这样会有问题吗?需要使用lock
吗?
我还想知道是否可以在列表对象上使用锁定及其Foreach<>
方法。
是的,对于一个 List<>
,添加或移除元素是不线程安全的,所以需要同步访问,例如使用 lock
。
请注意,lock
关键字并不锁定你用作标识符的对象,它只是防止两个线程同时进入同一代码块。你需要在访问列表的 所有 代码周围加锁,并使用 相同的对象 作为标识符。
List
对象的内部变量中。如果两个线程同时添加项目,则由于List
类中的代码未考虑多个线程,因此内部变量可能会被破坏。因此,在多个线程更改列表时,您始终需要同步代码。 - GuffaList<T>
不是线程安全的,因此您需要使用锁来控制对列表的访问。如果有多个线程访问该列表,请确保它们都尊重锁,否则您将遇到问题。最好的方法是子类化List,以便自动发生锁定,否则您很可能最终会忘记。
实际上,有时List<>是线程安全的,有时不是,根据Microsoft:
此类型的公共静态成员是线程安全的。任何实例成员都不能保证是线程安全的。
但该页面继续说:
枚举集合本质上不是线程安全的过程。在罕见的情况下,其中一个枚举与一个或多个写访问竞争,确保线程安全的唯一方法是在整个枚举期间锁定集合。为了允许多个线程对集合进行读写访问,必须实现自己的同步。
List<T>
是线程安全的。集合不在存在多个读取器的情况下是线程不安全的情况非常罕见,因此在缺乏其他文档说明的情况下,这种程度的线程安全性被认为是默认的;尽管如此,我会说“永远”不是线程安全的集合只有像延迟集合这样的东西,其中两个同时进行的“读取”访问可能会导致冲突修改。 - supercatList<T>
集合保证一个线程的读取不会以任何干扰另一个状态的读取的方式改变其状态。事实上,在当前的实现中,读取不会改变其状态,但是将来的实现理论上可以通过设置“已删除”标志并推迟实际删除直到下一次读取较晚的项来实现Remove
。这样做的实现将需要... - supercat