安全執行緒集合Thread-Safe Collections

.NET Framework 4 引進了 System.Collections.Concurrent 命名空間,其中包含數個兼具安全執行緒與調整能力的集合類別。The .NET Framework 4 introduces the System.Collections.Concurrent namespace, which includes several collection classes that are both thread-safe and scalable. 多個執行緒可以安全且有效率地新增或移除這些集合中的項目,而不需要利用使用者程式碼進行額外同步處理。Multiple threads can safely and efficiently add or remove items from these collections, without requiring additional synchronization in user code. 當您撰寫新的程式碼時,只要多個執行緒將同時寫入集合,就使用並行集合類別。When you write new code, use the concurrent collection classes whenever multiple threads will write to the collection concurrently. 如果您僅讀取共用集合,則可以使用 System.Collections.Generic 命名空間中的類別。If you are only reading from a shared collection, then you can use the classes in the System.Collections.Generic namespace. 除非您需要將目標設為 .NET Framework 1.1 或舊版本的執行階段,否則建議您不要使用 1.0 集合類別。We recommend that you do not use 1.0 collection classes unless you are required to target the .NET Framework 1.1 or earlier runtime.

.NET Framework 1.0 和 2.0 集合中的執行緒同步處理Thread Synchronization in the .NET Framework 1.0 and 2.0 Collections

您可以在 System.Collections 命名空間中找到 .NET Framework 1.0 中引進的集合。The collections introduced in the .NET Framework 1.0 are found in the System.Collections namespace. 這些包括常用 ArrayListHashtable 的集合透過 Synchronized 屬性來提供某種安全執行緒,而這個屬性會傳回集合的安全執行緒包裝函式。These collections, which include the commonly used ArrayList and Hashtable, provide some thread-safety through the Synchronized property, which returns a thread-safe wrapper around the collection. 包裝函式的運作方式是針對每個新增或移除作業鎖定整個集合。The wrapper works by locking the entire collection on every add or remove operation. 因此,嘗試存取集合的每個執行緒都必須等待,直到輪到它取得一個鎖定。Therefore, each thread that is attempting to access the collection must wait for its turn to take the one lock. 這無法進行擴充,而且可能會造成大型集合的重大效能下降。This is not scalable and can cause significant performance degradation for large collections. 此外,設計未完全保護競爭情形。Also, the design is not completely protected from race conditions. 如需詳細資訊,請參閱泛型集合中的同步處理For more information, see Synchronization in Generic Collections.

您可以在 System.Collections.Generic 命名空間中找到 .NET Framework 2.0 中引進的集合類別,The collection classes introduced in the .NET Framework 2.0 are found in the System.Collections.Generic namespace. 包括 List<T>Dictionary<TKey,TValue> 等。These include List<T>, Dictionary<TKey,TValue>, and so on. 這些類別提供相較起 .NET Framework 1.0 類別的改良型別安全和效能。These classes provide improved type safety and performance compared to the .NET Framework 1.0 classes. 不過,.NET Framework 2.0 集合類別不會提供任何執行緒同步處理;在多個執行緒上同時新增或移除項目時,使用者程式碼必須提供所有同步處理。However, the .NET Framework 2.0 collection classes do not provide any thread synchronization; user code must provide all synchronization when items are added or removed on multiple threads concurrently.

建議您使用 NET Framework 4 中的並行集合類別,因為這些類別不僅提供 .NET Framework 2.0 集合類別的型別安全,而且提供比 .NET Framework 1.0 集合更高的效率及更完整的執行緒安全性。We recommend the concurrent collections classes in the .NET Framework 4 because they provide not only the type safety of the .NET Framework 2.0 collection classes, but also more efficient and more complete thread safety than the .NET Framework 1.0 collections provide.

更細緻的鎖定和無鎖定機制Fine-Grained Locking and Lock-Free Mechanisms

有些並行集合類型會使用輕量型同步處理機制,例如 .NET Framework 4 中新增的 SpinLockSpinWaitSemaphoreSlimCountdownEventSome of the concurrent collection types use lightweight synchronization mechanisms such as SpinLock, SpinWait, SemaphoreSlim, and CountdownEvent, which are new in the .NET Framework 4. 這些同步處理型別通常會先使用短期間的忙碌旋轉,再讓執行緒進入真正的 Wait 狀態。These synchronization types typically use busy spinning for brief periods before they put the thread into a true Wait state. 預期等候時間很短時,旋轉的費用遠低於等待,這包含昂貴的核心轉換。When wait times are expected to be very short, spinning is far less computationally expensive than waiting, which involves an expensive kernel transition. 針對使用旋轉的集合類別,這個效率表示多個執行緒可以使用極高的速率來新增和移除項目。For collection classes that use spinning, this efficiency means that multiple threads can add and remove items at a very high rate. 如需旋轉與封鎖比較的詳細資訊,請參閱 SpinLockSpinWaitFor more information about spinning vs. blocking, see SpinLock and SpinWait.

ConcurrentQueue<T>ConcurrentStack<T> 類別完全不使用鎖定。The ConcurrentQueue<T> and ConcurrentStack<T> classes do not use locks at all. 相反地,它們依賴 Interlocked 作業來取得安全執行緒。Instead, they rely on Interlocked operations to achieve thread-safety.

注意

因為並行集合類別支援 ICollection,所以會提供 IsSynchronizedSyncRoot 屬性的實作,即使這些屬性無關也是一樣。Because the concurrent collections classes support ICollection, they provide implementations for the IsSynchronized and SyncRoot properties, even though these properties are irrelevant. IsSynchronized 一律會傳回 false,而 SyncRoot 一律為 null (在 Visual Basic 中為 Nothing)。IsSynchronized always returns false and SyncRoot is always null (Nothing in Visual Basic).

下表列出 System.Collections.Concurrent 命名空間中的集合類型。The following table lists the collection types in the System.Collections.Concurrent namespace.

類型Type 說明Description
BlockingCollection<T> 提供任何可實作 IProducerConsumerCollection<T> 之類型的界限和封鎖功能。Provides bounding and blocking functionality for any type that implements IProducerConsumerCollection<T>. 如需詳細資訊,請參閱 BlockingCollection 概觀For more information, see BlockingCollection Overview.
ConcurrentDictionary<TKey,TValue> 索引鍵/值組字典的安全執行緒實作。Thread-safe implementation of a dictionary of key-value pairs.
ConcurrentQueue<T> FIFO (先進先出) 佇列的安全執行緒實作。Thread-safe implementation of a FIFO (first-in, first-out) queue.
ConcurrentStack<T> LIFO (後進先出) 堆疊的安全執行緒實作。Thread-safe implementation of a LIFO (last-in, first-out) stack.
ConcurrentBag<T> 未排序元素集合的安全執行緒實作。Thread-safe implementation of an unordered collection of elements.
IProducerConsumerCollection<T> 類型必須實作以在 BlockingCollection 中使用的介面。The interface that a type must implement to be used in a BlockingCollection.
標題Title 說明Description
BlockingCollection 概觀BlockingCollection Overview 描述 BlockingCollection<T> 類型所提供的功能。Describes the functionality provided by the BlockingCollection<T> type.
如何:在 ConcurrentDictionary 中新增和移除項目How to: Add and Remove Items from a ConcurrentDictionary 描述如何新增和移除 ConcurrentDictionary<TKey,TValue> 中的項目Describes how to add and remove elements from a ConcurrentDictionary<TKey,TValue>
如何:從 BlockingCollection 個別加入和擷取項目How to: Add and Take Items Individually from a BlockingCollection 描述在未使用唯讀列舉值的情況下,如何新增和擷取封鎖回收中的項目。Describes how to add and retrieve items from a blocking collection without using the read-only enumerator.
如何:將界限和封鎖功能加入至集合How to: Add Bounding and Blocking Functionality to a Collection 描述如何使用任何集合類別作為 IProducerConsumerCollection<T> 集合的基礎儲存機制。Describes how to use any collection class as the underlying storage mechanism for an IProducerConsumerCollection<T> collection.
如何:使用 ForEach 來移除 BlockingCollection 中的項目How to: Use ForEach to Remove Items in a BlockingCollection 描述如何使用 foreach (在 Visual Basic 中為 For Each) 來移除封鎖集合中的所有項目。Describes how to use foreach, (For Each in Visual Basic) to remove all items in a blocking collection.
如何:在管線中使用封鎖集合的陣列How to: Use Arrays of Blocking Collections in a Pipeline 描述如何同時使用多個封鎖回收來實作管線。Describes how to use multiple blocking collections at the same time to implement a pipeline.
如何:使用 ConcurrentBag 建立物件集區How to: Create an Object Pool by Using a ConcurrentBag 示範在您可以重複使用物件而非持續建立新物件的情況下,如何使用並行資料包改善效能。Shows how to use a concurrent bag to improve performance in scenarios where you can reuse objects instead of continually creating new ones.

參考資料Reference

System.Collections.Concurrent