安全執行緒集合

System.Collections.Concurrent 命名空間包含數個具備安全執行緒且可調整的集合類別。 多個執行緒可以安全且有效率地新增或移除這些集合中的項目,而不需要利用使用者程式碼進行額外同步處理。 當您撰寫新的程式碼時,請使用並行集合類別,以將多個執行緒同時寫入集合。 如果您只讀取共用集合,則可以使用 System.Collections.Generic 命名空間中的類別。

System.Collections 和 System.Collections.Generic

命名空間中的 System.Collections 集合類別包括 ArrayListHashtable。 這些類別會透過 Synchronized 屬性提供一些執行緒安全性,而這會傳回集合的安全執行緒包裝函式。 包裝函式的運作方式是針對每個新增或移除作業鎖定整個集合。 因此,嘗試存取集合的每個執行緒都必須等待,直到其可取得一個鎖定為止。 此流程無法調整,而且可能會嚴重降低大型集合的效能。 此外,這種設計無法避免競爭條件。 如需詳細資訊,請參閱泛型集合中的同步處理

命名空間中的 System.Collections.Generic 集合類別包括 List<T>Dictionary<TKey,TValue>。 這些類別提供 System.Collections 類別的改良類型安全和效能。 不過,System.Collections.Generic 類別不會提供任何執行緒同步處理;在多個執行緒上同時新增或移除項目時,使用者程式碼必須提供所有同步處理。

建議您在 System.Collections.Concurrent 命名空間中使用並行集合類別,因為該類別可提供型別安全,也提供更有效率且完整的執行緒安全性。

更細緻的鎖定和無鎖定機制

有些並行集合型別會使用輕量型同步處理機制,例如 SpinLockSpinWaitSemaphoreSlimCountdownEvent。 這些同步處理型別一般會先使用短期間的忙碌旋轉,再讓執行緒進入真正的 Wait 狀態。 如果預期等候的時間很短,旋轉費用就會遠低於等待成本,其中包含昂貴的核心轉換。 針對使用旋轉的集合類別,此效率表示多個執行緒可以高速率來新增和移除項目。 如需旋轉與封鎖的詳細資訊,請參閱 SpinLockSpinWait

ConcurrentQueue<T>ConcurrentStack<T> 類別完全不使用鎖定。 相反地,這些類別依賴 Interlocked 作業來取得執行緒安全性。

注意

因為並行集合類別支援 ICollection,所以會提供 IsSynchronizedSyncRoot 屬性的實作,即使這些屬性無關也是一樣。 IsSynchronized 一律會傳回 false,而 SyncRoot 一律為 null (在 Visual Basic 中為 Nothing)。

下表列出 System.Collections.Concurrent 命名空間中的集合型別:

類型 描述
BlockingCollection<T> 提供任何可實作 IProducerConsumerCollection<T> 之類型的界限和封鎖功能。 如需詳細資訊,請參閱 BlockingCollection 概觀
ConcurrentDictionary<TKey,TValue> 索引鍵/值組字典的安全執行緒實作。
ConcurrentQueue<T> FIFO (先進先出) 佇列的安全執行緒實作。
ConcurrentStack<T> LIFO (後進先出) 堆疊的安全執行緒實作。
ConcurrentBag<T> 未排序元素集合的安全執行緒實作。
IProducerConsumerCollection<T> 類型必須實作以在 BlockingCollection 中使用的介面。
標題 描述
BlockingCollection 概觀 描述 BlockingCollection<T> 類型所提供的功能。
作法:在 ConcurrentDictionary 中新增和移除項目 描述如何新增和移除 ConcurrentDictionary<TKey,TValue> 中的項目
作法:從 BlockingCollection 個別新增和擷取項目 描述在未使用唯讀列舉值的情況下,如何新增和擷取封鎖回收中的項目。
作法:將界限和封鎖功能新增至集合 描述如何使用任何集合類別作為 IProducerConsumerCollection<T> 集合的基礎儲存機制。
作法:使用 ForEach 來移除 BlockingCollection 中的項目 描述如何使用 foreach (在 Visual Basic 中為 For Each) 來移除封鎖集合中的所有項目。
作法:在管線中使用封鎖集合的陣列 描述如何同時使用多個封鎖回收來實作管線。
作法:使用 ConcurrentBag 建立物件集區 示範在您可以重複使用物件而非持續建立新物件的情況下,如何使用並行資料包改善效能。

參考