Compartir a través de


Estructuras de datos para programación paralela

.NET proporciona varios tipos que son útiles en la programación en paralelo, incluido un conjunto de clases de colección simultáneas, primitivos de sincronización ligera y tipos para la inicialización diferida. Puede usar estos tipos con cualquier código de aplicación multiproceso, incluida la biblioteca paralela de tareas y PLINQ.

Clases de colecciones simultáneas

Las clases de colecciones del espacio de nombres System.Collections.Concurrent ofrece operaciones de agregar y quitar seguras para subprocesos que evitan los bloqueos siempre que sea posible y usan el bloqueo específico cuando los bloqueos son necesarios. Una clase de colección simultánea no necesita que el código de usuario tome ningún bloqueo cuando accede a los elementos. Las clases de colección simultáneas pueden mejorar significativamente el rendimiento de los tipos como System.Collections.ArrayList y System.Collections.Generic.List<T> (con bloqueo implementado por el usuario) en escenarios en los que varios subprocesos agregan y quitan elementos de una colección.

En la tabla siguiente se enumeran las clases de colección simultáneas:

Tipo Descripción
System.Collections.Concurrent.BlockingCollection<T> Proporciona capacidades de bloqueo y establecimiento de límites en colecciones seguras para subprocesos que implementan System.Collections.Concurrent.IProducerConsumerCollection<T>. Los subprocesos de productor se bloquean si no hay ranuras disponibles o si la colección está llena. Los subprocesos de consumidor se bloquean si la colección está vacía. Este tipo también admite el acceso sin bloqueo por parte de los consumidores y productores. BlockingCollection<T> se puede usar como una clase base o un almacén de respaldo para proporcionar bloqueos y límites para cualquier clase de colección que admita IEnumerable<T>.
System.Collections.Concurrent.ConcurrentBag<T> Una implementación de contenedor segura para subprocesos que ofrece operaciones add y get escalables.
System.Collections.Concurrent.ConcurrentDictionary<TKey,TValue> Tipo de diccionario simultáneo y escalable.
System.Collections.Concurrent.ConcurrentQueue<T> Una cola FIFO simultánea y escalable.
System.Collections.Concurrent.ConcurrentStack<T> Una pila LIFO simultánea y escalable.

Para obtener más información, consulte Thread-Safe Colecciones.

Primitivos de sincronización

Los primitivos de sincronización del espacio de nombres System.Threading permiten un rendimiento más rápido y una simultaneidad específica al evitar mecanismos de bloqueo costosos que se encuentran en el código de multithreading heredado.

En la tabla siguiente se enumeran los tipos de sincronización:

Tipo Descripción
System.Threading.Barrier Permite que varios subprocesos funcionen en un algoritmo en paralelo proporcionando un punto en el que cada tarea puede indicar su llegada y, a continuación, bloquear hasta que algunas o todas las tareas hayan llegado. Para más información, consulte Barrier.
System.Threading.CountdownEvent Simplifica los escenarios de bifurcación y combinación proporcionando un mecanismo sencillo de encuentro. Para obtener más información, vea CountdownEvent.
System.Threading.ManualResetEventSlim Un primitivo de sincronización similar a System.Threading.ManualResetEvent. ManualResetEventSlim es más ligero, pero solo se puede usar para la comunicación dentro del proceso.
System.Threading.SemaphoreSlim Primitivo de sincronización que limita el número de subprocesos que pueden acceder simultáneamente a un recurso o a un grupo de recursos. Para obtener más información, vea Semáforo y SemáforoSlim.
System.Threading.SpinLock Un primitivo de bloqueo de exclusión mutua genera el subproceso que trata de obtener un bloqueo para esperar en un bucle, o girar, durante un período de tiempo antes de producir su cuanto. En escenarios en los que se espera que la espera por el bloqueo sea breve, SpinLock ofrece un mejor rendimiento que otras formas de bloqueo. Para obtener más información, consulte SpinLock.
System.Threading.SpinWait Un tipo pequeño y ligero que girará durante un tiempo especificado y, finalmente, colocará el hilo en un estado de espera si se supera el conteo de giros. Para obtener más información, consulte SpinWait.

Para obtener más información, consulte:

Clases de inicialización diferida

Con la inicialización diferida, la memoria de un objeto no se asigna hasta que sea necesaria. La inicialización diferida puede mejorar el rendimiento al distribuir las asignaciones de objetos uniformemente durante la vigencia de un programa. Puede habilitar la inicialización diferida para cualquier tipo personalizado ajustando el tipo Lazy<T>.

En la tabla siguiente se enumeran los tipos de inicialización diferida:

Tipo Descripción
System.Lazy<T> Proporciona una inicialización diferida segura para subprocesos y ligera.
System.Threading.ThreadLocal<T> Proporciona un valor inicializado de forma diferida por cada subproceso, donde cada subproceso invoca de forma diferida la función de inicialización.
System.Threading.LazyInitializer Proporciona métodos estáticos que evitan la necesidad de asignar una instancia de inicialización diferida y dedicada. En su lugar, usan referencias para garantizar que los destinos se han inicializado a medida que se accede a ellos.

Para obtener más información, consulte Inicialización diferida.

Excepciones agregadas

El System.AggregateException tipo se puede usar para capturar varias excepciones que se inician simultáneamente en subprocesos independientes y devolverlas al subproceso de combinación como una única excepción. Los tipos System.Threading.Tasks.Task y System.Threading.Tasks.Parallel y PLINQ usan AggregateException ampliamente para este propósito. Para obtener más información, vea Control de excepciones y Cómo: Controlar excepciones en una consulta PLINQ.

Consulte también