2011-08-05 77 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

如果您退回列表您仍然無法修改原始列表 如果您正在考慮反射,也可以繞過運行時檢查。 你怎麼能使一個領域私人?你可能會用私人密碼工作。我可以用我可以訪問的思考來回答你。 –