ReadOnlyCollection<T> 執行緒安全
ReadOnlyCollection(of T) 的文件指出:
A ReadOnlyCollection(Of T)可以同時支持多個閱讀器,只要不修改集合即可。即便如此,通過集合列舉本質上不是執行緒安全的過程。為了保證列舉過程中的執行緒安全,可以在整個列舉過程中鎖定集合。要允許集合被多個執行緒訪問以進行讀寫,您必須實現自己的同步。我的問題是關於粗體部分:
- 為什麼通過集合列舉本質上不是執行緒安全的
- 可能的影響是什麼,以及
- 常用的解決方法是什麼?
C# 有一個非常好的集合模型,但 ReadOnlyCollection 類是整個模型中最不幸的構思(或命名)的類之一。它應該更恰當地稱為只讀列表,而不是只讀集合。
現在,要回答您的問題,它只是在構造時提供的 IList 的只讀裝飾器。因此,構造 ReadOnlyCollection 的程式碼可能會修改原始列表,這將對多執行緒訪問產生所有後果。
因此,如果集合真的是只讀的,那麼列舉集合將是執行緒安全的;但由於它不是只讀的,因此它不是執行緒安全的。鑑於您擁有的聲譽,我很確定您不會想知道為什麼通過非只讀集合進行列舉不是執行緒安全的。
至於您詢問的解決方法,您可以使用鎖定,也可以使用無鎖(或盡可能少地鎖定)原則並製作列表的真正只讀副本。
編輯
幾個月後,我重新閱讀了我的答案(感謝 asyncwait 的評論),我意識到我應該回答所有 OP 的問題,而不是根據他的聲譽做出假設。OP現在可能已經收到了他的答案,但為了未來的讀者,我會這樣做。
通過非真正只讀集合進行列舉本質上不是執行緒安全的,原因與即使在單執行緒場景中您也無法在列舉集合時修改集合的原因相同。(Java 中的 ConcurrentModificationException,C# 中的 InvalidOperationException。)在單執行緒場景中,您可以確保您的列舉程式碼不會嘗試以任何方式更改集合,但在多執行緒場景中,一個執行緒可能會在列舉集合的同時另一個執行緒可能正在同時更改它。