2011-08-05 35 views
25

下面的伪代码是线程安全的吗?是列表<T>线程安全的阅读?

IList<T> dataList = SomeNhibernateRepository.GetData(); 

Parallel.For(..i..) 
{ 
    foreach(var item in dataList) 
    { 
     DoSomething(item); 
    } 
} 

该列表永远不会被更改,它只能被迭代和并行读取。不要写字段或类似的东西。

谢谢。

回答

38

是的,List<T>可以同时读取多个线程,只要没有任何东西写入。

the documentation

一个List<T>可以支持多个读者同时,只要收集不被修改。

编辑:请注意,您的代码不一定使用List<T> - 只是一个IList<T>。你知道GetData()返回的类型吗?如果你在控制GetData(),你可能想要记录它返回的列表对于阅读是线程安全的,如果它实际上返回List<T>

3

只要DoSomething(item)不修改dataList它完全线程安全。既然你说过没有,那么是的,这是线程安全的。

0

如果你说的话是正确的,那么我会这么说。但是你所说或所想的可能不是现实中发生的事情。你如何在代码中说出你所说的话。如何执行List从未被修改的约束?

+3

这是比较容易访问它:使它在一个类只能执行读取访问列表中的私有成员,可能暴露通过其他成员的值。这个类需要被控制,但它只是一个代码。 –

1

,以确保没有人能改变我上你的列表,你可以通过一个IEnumerable

IEnumerable<T> dataList = SomeNhibernateRepository.GetData(); 

Parallel.For(..i..) 
{ 
    foreach(var item in dataList) 
    { 
     DoSomething(item); 
    } 
} 
+0

这仍然可以退回列表。您可以返回列表 .AsReadOnly(),但即使如此,原始列表可通过反射访问。 – Janiels

+1

如果您退回列表您仍然无法修改原始列表 如果您正在考虑反射,也可以绕过运行时检查。 你怎么能使一个领域私人?你可能会用私人密码工作。我可以用我可以访问的思考来回答你。 –