Estructuras de datos para la programación paralela

En .NET se proporcionan varios tipos que son útiles para la programación en paralelo, incluido un conjunto de clases de colecciones 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, como la biblioteca TPL 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 colecciones simultáneas pueden mejorar significativamente el rendimiento a través de tipos como System.Collections.ArrayList y System.Collections.Generic.List<T> (con bloqueo implementado por el usuario) en escenarios donde varios subprocesos agregarán y quitarán elementos de una colección.

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

Tipo Description
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 de productores y consumidores. BlockingCollection<T> puede utilizarse como una clase base o una memoria auxiliar para proporcionar el bloqueo y el establecimiento de límite de cualquier clase de colección que admite 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> Un tipo de diccionario simultáneo y escalable.
System.Collections.Concurrent.ConcurrentQueue<T> Un tipo de cola FIFO simultánea y escalable.
System.Collections.Concurrent.ConcurrentStack<T> Un tipo de pila LIFO simultánea y escalable.

Para obtener más información, consulte Colecciones seguras para subprocesos.

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 pueda señalizar su llegada y después bloquearse hasta que llegan algunas tareas o todas. 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 más información, vea CountdownEvent.
System.Threading.ManualResetEventSlim Un primitivo de sincronización similar a System.Threading.ManualResetEvent. ManualResetEventSlim es ligero, pero solo puede utilizarse para la comunicación dentro de un proceso.
System.Threading.SemaphoreSlim Un primitivo de sincronización que limita el número de subprocesos que acceden simultáneamente a un recurso o a un conjunto de recursos. Para más información, vea Semaphore y SemaphoreSlim.
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 prevé que la espera del bloqueo sea corta, SpinLock ofrece mayor rendimiento que otras formas de bloqueo. Para más información, vea SpinLock.
System.Threading.SpinWait Un tipo pequeño y ligero que girará durante un tiempo especificado y, finalmente, colocará el subproceso en un estado de espera si se supera el número de giros. Para más información, vea SpinWait.

Para más información, consulte:

Clases de inicialización diferida

Con la inicialización diferida, no se asigna la memoria para un objeto hasta que se necesite. La inicialización diferida puede mejorar el rendimiento al distribuir las asignaciones de objetos uniformemente a lo largo de la duración 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, vea Inicialización diferida.

Agregar excepciones

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

Vea también