Colecciones seguras para subprocesos

.NET Framework 4 introduce el espacio de nombres System.Collections.Concurrent, que incluye varias clases de colección que son a la vez seguras para subprocesos y escalables. Varios subprocesos pueden agregar o quitar elementos de estas colecciones sin ningún riesgo y de un modo eficaz, sin requerir una sincronización adicional en código de usuario. Al escribir un código nuevo, utilice las clases de colección simultáneas siempre que varios subprocesos se vayan a escribir en la colección de forma simultánea. Si solo está leyendo en una colección compartida, puede utilizar las clases en el espacio de nombres System.Collections.Generic. Recomendamos no utilizar clases de colección 1.0 a menos que estén destinadas a .NET Framework 1.1. o un runtime de una versión anterior.

Sincronización de subprocesos en las colecciones de .NET Framework 1.0 y 2.0

Las colecciones introducidas en .NET Framework 1.0 se encuentran en el espacio de nombres System.Collections. Estas colecciones, que incluyen ArrayList y Hashtable utilizados habitualmente, proporcionan cierta seguridad para subprocesos mediante la propiedad Synchronized, que devuelve un contenedor seguro para subprocesos en torno a la colección. El contenedor funciona bloqueando toda la colección en cada operación de agregar o quitar. Por consiguiente, cada subproceso que intenta tener acceso a la colección debe esperar su turno para tomar el único bloqueo. Esto no es escalable y puede producir una degradación significativa del rendimiento en las colecciones grandes. Asimismo, el diseño no está totalmente protegido de las condiciones de carrera. Para obtener más información, vea Synchronization in Generic Collections (Sincronización de colecciones genéricas).

Las clases de colección introducidas en .NET Framework 2.0 se encuentran en el espacio de nombres System.Collections.Generic. Éstas incluyen List<T>, Dictionary<TKey,TValue>, etc. Estas clases proporcionan una seguridad de tipos y un rendimiento mejorados comparados con las clases de .NET Framework 1.0. Sin embargo, las clases de colección de .NET Framework 2.0 no proporcionan ninguna sincronización de subprocesos; el código de usuario debe proporcionar toda la sincronización cuando se agregan o quitan elementos en varios subprocesos simultáneamente.

Se recomiendan las clases de colección simultáneas en .NET Framework 4 porque proporcionan no solo la seguridad de tipos de las clases de colección de .NET Framework 2.0, sino también una seguridad de subprocesos más eficaz y completa que las colecciones de .NET Framework 1.0.

Mecanismos de bloqueo específico y sin bloqueos

Algunos de los tipos de colección simultáneos utilizan mecanismos de sincronización ligeros como SpinLock, SpinWait, SemaphoreSlim y CountdownEvent, que son nuevos en .NET Framework 4. Estos tipos de sincronización utilizan normalmente giro de ocupado durante breves períodos antes de colocar el subproceso en un verdadero estado de espera. Cuando se prevé que los tiempos de espera sean muy cortos, el giro es técnicamente menos costoso que la espera, que implica una costosa transición del kernel. Para las clases de colección que utilizan el giro, esta eficacia significa que se pueden agregar y quitar varios subprocesos con una tasa muy alta. Para más información sobre la comparación del giro y el bloque, consulte SpinLock y SpinWait.

Las clases ConcurrentQueue<T> y ConcurrentStack<T> no utilizan bloqueos en absoluto. En su lugar, dependen de las operaciones Interlocked para lograr la seguridad para subprocesos.

Nota

Como las clases de colección simultáneas son compatibles con ICollection, proporcionan implementaciones para las propiedades IsSynchronized y SyncRoot, aunque estas propiedades sean irrelevantes. IsSynchronized devuelve siempre false y SyncRoot es siempre null (Nothing en Visual Basic).

La siguiente tabla enumera los tipos de colección en el espacio de nombres System.Collections.Concurrent.

Tipo Descripción
BlockingCollection<T> Proporciona funcionalidad de límite y bloqueo para cualquier tipo que implemente IProducerConsumerCollection<T>. Para obtener más información, consulte Información general sobre BlockingCollection.
ConcurrentDictionary<TKey,TValue> Implementación segura para subprocesos de un diccionario de pares clave-valor.
ConcurrentQueue<T> Implementación segura para subprocesos de una cola FIFO (primero en entrar, primero en salir).
ConcurrentStack<T> Implementación segura para subprocesos de una pila LIFO (último en entrar, primero en salir).
ConcurrentBag<T> Implementación segura para subprocesos de una colección no ordenada de elementos.
IProducerConsumerCollection<T> Interfaz que debe implementar un tipo para su uso en BlockingCollection.
Title Descripción
Información general sobre BlockingCollection Describe la funcionalidad proporcionada por el tipo BlockingCollection<T>.
Cómo: agregar y quitar elementos de ConcurrentDictionary Describe cómo agregar y quitar los elementos de ConcurrentDictionary<TKey,TValue>
Cómo: agregar y tomar elementos de forma individual en una clase BlockingCollection Describe cómo agregar y recuperar elementos de una colección de bloqueo sin utilizar el enumerador de solo lectura.
Cómo: agregar la funcionalidad de límite y bloqueo a una colección Describe cómo utilizar cualquier clase de colección como mecanismo de almacenamiento subyacente para una colección IProducerConsumerCollection<T>.
Cómo: utilizar ForEach para quitar elementos de BlockingCollection Describe cómo utilizar foreach, (For Each en Visual Basic) para quitar todos los elementos en una colección de bloqueo.
Cómo: usar matrices de colecciones de bloqueo en una canalización Describe cómo utilizar varias colecciones de bloqueo para implementar una canalización al mismo tiempo.
Cómo: crear un grupo de objetos usando ConcurrentBag Muestra cómo usar un controlador simultáneo para mejorar el rendimiento en escenarios donde puede reutilizar objetos en lugar de crear continuamente otros nuevos.

Referencia

System.Collections.Concurrent