线程安全集合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. 建议不要使用 1.0 集合类,除非需要定位 .NET Framework 1.1 或更低版本运行时。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

.NET Framework 1.0 中引入的集合位于 System.Collections 命名空间中。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.

.NET Framework 2.0 中引入的集合类位于 System.Collections.Generic 命名空间中。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

某些并发集合类型使用轻量同步机制,如 SpinLockSpinWaitSemaphoreSlimCountdownEvent,这些机制是 .NET Framework 4 中的新增功能。Some of the concurrent collection types use lightweight synchronization mechanisms such as SpinLock, SpinWait, SemaphoreSlim, and CountdownEvent, which are new in the .NET Framework 4. 这些同步类型通常在将线程真正置于等待状态之前,会在短时间内使用忙旋转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.
TitleTitle 说明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