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:
Cómo: Utilizar SpinLock para la sincronización de bajo nivel
Procedimiento: Sincronizar operaciones simultáneas con una clase Barrier.
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.