C# 为列表创建和分配值是否是线程安全的?

C# 为列表创建和分配值是否是线程安全的?,c#,synchronization,thread-safety,C#,Synchronization,Thread Safety,我对列表集合的线程安全性有疑问 这是我的测试课: Test t = new Test(); t.a = 100; t.b = 20; t.c = 10; 那么假设已经创建了10个以上的实例,并将其添加到列表中,如下所示 List<Test> tCollection = new List<Test>(); tCollection.add(t); 将对象添加到列表和通过列表进行迭代是线程安全的吗?答案是否定的 通常的集合都是非线程安全的 您必须使用集合的线程安全类似物*。

我对列表集合的线程安全性有疑问

这是我的测试课:

Test t = new Test();
t.a = 100;
t.b = 20;
t.c = 10;
那么假设已经创建了10个以上的实例,并将其添加到列表中,如下所示

List<Test> tCollection = new List<Test>();
tCollection.add(t);
将对象添加到列表和通过列表进行迭代是线程安全的吗?

答案是否定的

通常的集合都是非线程安全的

您必须使用集合的线程安全类似物*。阅读有关这些收藏的更多信息。

答案是否定的

通常的集合都是非线程安全的


您必须使用集合的线程安全类似物*。阅读有关这些集合的详细信息。

默认的.net集合不是线程安全的。 这意味着它们不包含处理多线程访问的额外代码,因为这样的代码会降低它们在单线程场景中的性能

正如亚历山大·高尔金(Alexander Galkin)在另一个答案中所说,微软提供了一些帮助。但是,您会注意到,没有任何ConcurrentList的工作方式与列表完全相同。这是因为创建一个具有列表所有属性(如随机访问、插入和删除)以及良好性能的线程安全列表实际上是不可能的。 在您的案例中,最接近的等效项是or

但是,对于您的情况,可能有一种更简单的方法: 对列表的只读访问始终是线程安全的。只要不更改列表,就可以从任意多个线程中迭代列表或访问随机元素

向列表中添加元素不是线程安全的。如果在添加元素时迭代列表,这一点很明显,您将得到一个异常:枚举数实例化后,集合被修改

但是,即使在不同时迭代列表的情况下从多个线程添加元素也不安全。您不会得到如此明显的错误,相反,它有时有效,有时无效

如果在程序启动后只添加一次元素,则可以使用普通列表。在单个writer线程中将元素添加到列表时,只需确保还没有启动读取器线程。将所有元素添加到列表后,可以从任意多个线程对其进行迭代


对于更复杂的场景,通常最好切换到ConcurrentQueue或ConcurrentStack,而不是使用锁实现自己的线程安全方法。

默认的.net集合不是线程安全的。 这意味着它们不包含处理多线程访问的额外代码,因为这样的代码会降低它们在单线程场景中的性能

正如亚历山大·高尔金(Alexander Galkin)在另一个答案中所说,微软提供了一些帮助。但是,您会注意到,没有任何ConcurrentList的工作方式与列表完全相同。这是因为创建一个具有列表所有属性(如随机访问、插入和删除)以及良好性能的线程安全列表实际上是不可能的。 在您的案例中,最接近的等效项是or

但是,对于您的情况,可能有一种更简单的方法: 对列表的只读访问始终是线程安全的。只要不更改列表,就可以从任意多个线程中迭代列表或访问随机元素

向列表中添加元素不是线程安全的。如果在添加元素时迭代列表,这一点很明显,您将得到一个异常:枚举数实例化后,集合被修改

但是,即使在不同时迭代列表的情况下从多个线程添加元素也不安全。您不会得到如此明显的错误,相反,它有时有效,有时无效

如果在程序启动后只添加一次元素,则可以使用普通列表。在单个writer线程中将元素添加到列表时,只需确保还没有启动读取器线程。将所有元素添加到列表后,可以从任意多个线程对其进行迭代


对于更复杂的场景,通常最好切换到ConcurrentQueue或ConcurrentStack,而不是使用锁实现您自己的线程安全方法。

这意味着,以下是线程安全的,在迭代时更改项的属性t可以吗。tCollection{//do calculation}中的foreachTest t从多个线程更改同一项的属性可能是线程安全的,也可能不是线程安全的,具体取决于该项。但在这种情况下,你是否只有一个项目或一个列表并不重要。您只需要确保您的项目是线程安全的。如果您不确定它是否是线程安全的,则可能不是。在这种情况下,您需要使用lock进行自己的同步,线程安全集合无法帮助您实现同步
ad-safe,可以在迭代时更改项目的属性t吗。tCollection{//do calculation}中的foreachTest t从多个线程更改同一项的属性可能是线程安全的,也可能不是线程安全的,具体取决于该项。但在这种情况下,你是否只有一个项目或一个列表并不重要。您只需要确保您的项目是线程安全的。如果您不确定它是否是线程安全的,则可能不是。在这种情况下,您需要使用lock进行自己的同步,线程安全的集合无法帮助您实现同步。
foreach(Test t in tCollection)
{
// do calculation 
}