共用方式為


執行緒安全的集合

命名空間 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。 這些同步類型通常會先使用忙碌旋轉一段時間,然後再將線程置於真正的狀態。 當預期等候時間較短時,自旋的計算成本遠低於等待,因為等待涉及昂貴的內核切換。 對於使用旋轉的集合類別,此效率表示多個線程可以高速率新增和移除專案。 如需旋轉與封鎖的詳細資訊,請參閱 SpinLockSpinWait

ConcurrentQueue<T>ConcurrentStack<T> 類別完全不會使用鎖定。 相反地,他們依賴 Interlocked 作業來達到線程安全性。

備註

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

下表列出 命名空間中的 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 中的項目 描述如何使用 foreachFor Each 在 Visual Basic 中) 移除封鎖集合中的所有專案。
如何:在管線中使用封鎖集合的陣列 描述如何同時使用多個封鎖集合來實作管線。
如何:使用 ConcurrentBag 建立物件集區 示範如何在您可以重複使用物件而不是持續建立新對象的情況下,使用並行包來改善效能。

參考文獻