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 nuevo código, utilice las clases de colección simultáneas siempre que la colección se escriba en varios subprocesos simultáneamente. 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 en el sitio web de MSDN.

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.

Recomendamos 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 obtener más información sobre el giro en comparación con el bloqueo, vea SpinLock y SpinWait.

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

NotaNota

Como las clases de colección simultáneas son compatibles con ICollection, proporcionan implementaciones para las propiedades SyncRoot y IsSynchronized, 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, vea Información general sobre BlockingCollection.

ConcurrentDictionary<TKey, TValue>

Implementación segura para subprocesos de un diccionario de pares de clave y 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.

Temas relacionados

Título

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 clase de 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