是否为List <t>线程安全创建和赋值?</t>

时间:2014-05-25 04:00:20

标签: c# synchronization thread-safety

我对List<T>集合的线程安全性有疑问。

这是我的测试类:

Test t = new Test();
t.a = 100;
t.b = 20;
t.c = 10;

然后让我们说上面的10个实例已经创建并添加到List中,如下所示。

List<Test> tCollection = new List<Test>();
tCollection.add(t);

稍后我在tCollection中遍历测试对象。

foreach(Test t in tCollection)
{
// do calculation 
}

将对象添加到List<Test>并通过List<Test>进行迭代是否是线程安全的?

2 个答案:

答案 0 :(得分:3)

答案是

通常的收藏品都是非线程安全的

您必须使用集合* 的线程安全类似物。详细了解这些集合on MSDN

答案 1 :(得分:2)

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

正如亚历山大加尔金在另一个答案中所说,微软提供了一些collections that are tailor-made for multi-threaded access。但是,您会注意到没有ConcurrentList<T>与List完全相同。这是因为创建具有列表的所有属性的线程安全列表,例如随机访问,插入和删除良好的性能几乎是不可能的。 在您的情况下,最接近的等价物是System.Collections.Concurrent.ConcurrentQueue<T>ConcurrentStack<T>

但是,在您的情况下可能会有一种更简单的方法:
对列表的只读访问始终是线程安全的。您可以根据需要迭代列表或访问随机元素,只要您不更改列表即可。

向列表中添加元素不是线程安全的。如果你在添加元素时迭代列表,这将是显而易见的,你会得到一个例外:&#34;在枚举器被实例化之后修改了集合&#34;

但即使从多个线程添加元素而不同时迭代列表也是不安全的。你不会得到这样一个明显的错误,相反它有时会起作用,有时也不行。

如果您只在程序启动后添加一次元素,那么您可以使用普通列表。在单个编写器线程中向列表添加元素时,请确保没有启动读取器线程。将所有元素添加到列表后,可以根据需要从多个线程迭代它。

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