安全執行緒集合
System.Collections.Concurrent 命名空間包含數個具備安全執行緒且可調整的集合類別。 多個執行緒可以安全且有效率地新增或移除這些集合中的項目,而不需要利用使用者程式碼進行額外同步處理。 當您撰寫新的程式碼時,請使用並行集合類別,以將多個執行緒同時寫入集合。 如果您只讀取共用集合,則可以使用 System.Collections.Generic 命名空間中的類別。
System.Collections 和 System.Collections.Generic
命名空間中的 System.Collections 集合類別包括 ArrayList 和 Hashtable。 這些類別會透過 Synchronized
屬性提供一些執行緒安全性,而這會傳回集合的安全執行緒包裝函式。 包裝函式的運作方式是針對每個新增或移除作業鎖定整個集合。 因此,嘗試存取集合的每個執行緒都必須等待,直到其可取得一個鎖定為止。 此流程無法調整,而且可能會嚴重降低大型集合的效能。 此外,這種設計無法避免競爭條件。 如需詳細資訊,請參閱泛型集合中的同步處理。
命名空間中的 System.Collections.Generic 集合類別包括 List<T> 和 Dictionary<TKey,TValue>。 這些類別提供 System.Collections 類別的改良類型安全和效能。 不過,System.Collections.Generic 類別不會提供任何執行緒同步處理;在多個執行緒上同時新增或移除項目時,使用者程式碼必須提供所有同步處理。
建議您在 System.Collections.Concurrent 命名空間中使用並行集合類別,因為該類別可提供型別安全,也提供更有效率且完整的執行緒安全性。
更細緻的鎖定和無鎖定機制
有些並行集合型別會使用輕量型同步處理機制,例如 SpinLock、SpinWait、SemaphoreSlim 和 CountdownEvent。 這些同步處理型別一般會先使用短期間的忙碌旋轉,再讓執行緒進入真正的 Wait
狀態。 如果預期等候的時間很短,旋轉費用就會遠低於等待成本,其中包含昂貴的核心轉換。 針對使用旋轉的集合類別,此效率表示多個執行緒可以高速率來新增和移除項目。 如需旋轉與封鎖的詳細資訊,請參閱 SpinLock 和 SpinWait。
ConcurrentQueue<T> 和 ConcurrentStack<T> 類別完全不使用鎖定。 相反地,這些類別依賴 Interlocked 作業來取得執行緒安全性。
注意
因為並行集合類別支援 ICollection,所以會提供 IsSynchronized 和 SyncRoot 屬性的實作,即使這些屬性無關也是一樣。 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 建立物件集區 | 示範在您可以重複使用物件而非持續建立新物件的情況下,如何使用並行資料包改善效能。 |