Estruturas de Dados para Programação Paralela
O .NET fornece vários tipos que são úteis na programação paralela, incluindo um conjunto de classes de coleção simultâneas, primitivas de sincronização leves e tipos para inicialização lenta. Você pode usar esses tipos com qualquer código de aplicativo multithreaded, incluindo a Biblioteca Paralela de Tarefas e o PLINQ.
Classes de coleção simultânea
As classes de coleção no System.Collections.Concurrent namespace fornecem operações de adição e remoção seguras para threads que evitam bloqueios sempre que possível e usam bloqueios refinados onde os bloqueios são necessários. Uma classe de coleção simultânea não requer código de usuário para executar bloqueios quando acessa itens. As classes de coleção simultâneas podem melhorar significativamente o desempenho em tipos como System.Collections.ArrayList e System.Collections.Generic.List<T> (com bloqueio implementado pelo usuário) em cenários em que vários threads adicionam e removem itens de uma coleção.
A tabela a seguir lista as classes de coleção simultâneas:
Tipo | Description |
---|---|
System.Collections.Concurrent.BlockingCollection<T> | Fornece recursos de bloqueio e delimitação para coleções thread-safe que implementam System.Collections.Concurrent.IProducerConsumerCollection<T>o . Os threads do produtor bloqueiam se não houver slots disponíveis ou se a coleção estiver cheia. Os threads do consumidor bloqueiam se a coleção estiver vazia. Este tipo também apoia o acesso sem bloqueio por parte dos consumidores e produtores. BlockingCollection<T> pode ser usado como uma classe base ou armazenamento de suporte para fornecer bloqueio e delimitação para qualquer classe de coleção que ofereça suporte a IEnumerable<T>. |
System.Collections.Concurrent.ConcurrentBag<T> | Uma implementação de saco thread-safe que fornece operações escaláveis de adição e obtenção. |
System.Collections.Concurrent.ConcurrentDictionary<TKey,TValue> | Um tipo de dicionário simultâneo e escalável. |
System.Collections.Concurrent.ConcurrentQueue<T> | Uma fila FIFO simultânea e escalável. |
System.Collections.Concurrent.ConcurrentStack<T> | Uma pilha LIFO simultânea e escalável. |
Para obter mais informações, consulte Coleções Thread-Safe.
Primitivos de sincronização
As primitivas de sincronização no namespace permitem simultaneidade refinada System.Threading e desempenho mais rápido, evitando mecanismos de bloqueio caros encontrados no código multithreading herdado.
A tabela a seguir lista os tipos de sincronização:
Tipo | Description |
---|---|
System.Threading.Barrier | Permite que vários threads trabalhem em um algoritmo em paralelo, fornecendo um ponto no qual cada tarefa pode sinalizar sua chegada e, em seguida, bloquear até que algumas ou todas as tarefas tenham chegado. Para obter mais informações, consulte Barreira. |
System.Threading.CountdownEvent | Simplifica os cenários de bifurcação e junção, fornecendo um mecanismo de encontro fácil. Para obter mais informações, consulte CountdownEvent. |
System.Threading.ManualResetEventSlim | Uma primitiva de sincronização semelhante a System.Threading.ManualResetEvent. ManualResetEventSlim é mais leve, mas só pode ser usado para comunicação dentro do processo. |
System.Threading.SemaphoreSlim | Uma primitiva de sincronização que limita o número de threads que podem acessar simultaneamente um recurso ou um pool de recursos. Para obter mais informações, consulte Semaphore e SemaphoreSlim. |
System.Threading.SpinLock | Uma primitiva de bloqueio de exclusão mútua que faz com que o thread que está tentando adquirir o bloqueio aguarde em um loop, ou spin, por um período de tempo antes de produzir seu quantum. Em cenários onde se espera que a espera pelo bloqueio seja curta, SpinLock oferece melhor desempenho do que outras formas de bloqueio. Para obter mais informações, consulte SpinLock. |
System.Threading.SpinWait | Um tipo pequeno e leve que girará por um tempo especificado e, eventualmente, colocará o thread em um estado de espera se a contagem de rotação for excedida. Para obter mais informações, consulte SpinWait. |
Para obter mais informações, consulte:
Classes de inicialização lentas
Com a inicialização lenta, a memória de um objeto não é alocada até que seja necessária. A inicialização lenta pode melhorar o desempenho distribuindo as alocações de objetos uniformemente ao longo da vida útil de um programa. Você pode habilitar a inicialização lenta para qualquer tipo personalizado encapsulando o tipo Lazy<T>.
A tabela a seguir lista os tipos de inicialização lenta:
Tipo | Description |
---|---|
System.Lazy<T> | Fornece inicialização lenta leve e segura para threads. |
System.Threading.ThreadLocal<T> | Fornece um valor inicializado preguiçosamente por thread, com cada thread invocando preguiçosamente a função de inicialização. |
System.Threading.LazyInitializer | Fornece métodos estáticos que evitam a necessidade de alocar uma instância de inicialização lenta dedicada. Em vez disso, eles usam referências para garantir que os destinos tenham sido inicializados à medida que são acessados. |
Para obter mais informações, consulte Inicialização lenta.
Exceções agregadas
O System.AggregateException tipo pode ser usado para capturar várias exceções que são lançadas simultaneamente em threads separados e devolvê-las ao thread de junção como uma única exceção. Os System.Threading.Tasks.Task e System.Threading.Tasks.Parallel tipos e PLINQ uso AggregateException extensivamente para este fim. Para obter mais informações, consulte Tratamento de exceções e Como manipular exceções em uma consulta PLINQ.