Partilhar via


Quando usar uma coleção de Thread-Safe.

O .NET Framework versão 4 apresenta cinco novos tipos de coleção que são especialmente projetados para suportar vários segmentos adicionar e remover operações. Para obter a segurança do thread, esses novos tipos de usam vários tipos de bloqueio eficiente e mecanismos de sincronização sem bloqueio. Sincronização adiciona sobrecarga para uma operação. A quantidade de sobrecarga depende do tipo de sincronização é usado, o tipo de operações que são executadas e outros fatores como, por exemplo, o número de segmentos que está tentando acessar simultaneamente a coleção.

Em alguns cenários, sincronização sobrecarga é irrisório e permite que o tipo de vários segmentos de desempenho significativamente mais rápido e dimensionar muito melhor do que o seu equivalente de thread safe quando protegido por um bloqueio externo. Em outros cenários, a sobrecarga pode fazer com que o tipo de thread-safe, executar e alterar a escala sobre o mesmo ou até mesmo mais lentamente do que a versão externamente bloqueado, o thread safe do tipo.

As seções a seguir fornecem orientações gerais sobre quando usar uma coleção de thread-safe versus seu equivalente de thread safe tem um bloqueio fornecido pelo usuário ao redor de sua leitura e gravação de operações. Porque o desempenho pode variar dependendo de vários fatores, a orientação não é específica e não é necessariamente válida em todas as circunstâncias. Se o desempenho é muito importante, é a melhor maneira de determinar qual tipo de coleção para usar medir o desempenho com base em cargas e as configurações do computador representativo. Este documento usa os seguintes termos:

  • Cenário de consumidor de produtor puro
    Qualquer segmento de dado é adicionando ou removendo elementos, mas não ambos.

  • Cenário de consumidor de produtor misto
    Qualquer segmento de dado é tanto adicionando e removendo elementos.

  • Aumento de velocidade
    Mais rápido desempenho algorítmico em relação ao outro tipo no mesmo cenário.

  • Escalabilidade
    O aumento no desempenho é proporcional ao número de núcleos no computador. Um algoritmo que ajusta o desempenho mais rápido em oito núcleos que em dois núcleos.

ConcurrentQueue(T) vs.Queue(T)

Em cenários de produtor-consumidor puro, onde o tempo de processamento para cada elemento é muito pequeno (algumas instruções), em seguida, System.Collections.Concurrent.ConcurrentQueue<T> pode oferecer os benefícios de desempenho modestos através de um System.Collections.Generic.Queue<T> que tem um bloqueio externo. Nesse cenário, ConcurrentQueue<T> funciona melhor quando um thread dedicado é enfileiramento de mensagens e um thread dedicado é de-queuing. Se você não aplicar essa regra, em seguida, Queue<T> pode realizar até mesmo um pouco mais rápido do que ConcurrentQueue<T> em computadores que possuem vários núcleos.

Quando o tempo de processamento é de cerca de 500 FLOPS (operações de ponto flutuante) ou mais, em seguida, a regra de dois segmentos não se aplica a ConcurrentQueue<T>, que então tem escalabilidade muito bom. Queue<T>não se adapta bem neste cenário.

No misto consumidor-produtor cenários, quando o tempo de processamento é muito pequeno, um Queue<T> que tem um externo bloqueio dimensiona melhor do que ConcurrentQueue<T> faz. No entanto, quando o tempo de processamento é cerca de 500 FLOPS ou mais, em seguida, a ConcurrentQueue<T> dimensiona melhor.

ConcurrentStack vs.Pilha

Em cenários de produtor-consumidor puro, quando o tempo de processamento é muito pequeno, em seguida, System.Collections.Concurrent.ConcurrentStack<T> e System.Collections.Generic.Stack<T> que tem um externo bloqueio provavelmente irá executar praticamente o mesmo com um segmento de colocar dedicado e um dedicado estalos thread. No entanto, como o aumento do número de threads, ambos os tipos lento devido a contenção de aumento e Stack<T> pode realizar melhor do que ConcurrentStack<T>. Quando o tempo de processamento é cerca de 500 FLOPS ou mais, em seguida, os dois tipos de escala em sobre a mesma taxa.

No misto consumidor-produtor cenários, ConcurrentStack<T> é mais rápido para pequenas e grandes cargas de trabalho.

O uso de PushRange e TryPopRangepode agilizar muito os tempos de acesso.

ConcurrentDictionary vs.Dicionário

Em geral, use um System.Collections.Concurrent.ConcurrentDictionary<TKey, TValue> em qualquer cenário onde você está adicionando e atualizando chaves ou valores simultaneamente de vários threads. Em cenários que envolvem atualizações freqüentes e leituras relativamente poucas, o ConcurrentDictionary<TKey, TValue> geralmente oferece benefícios modestos. Em cenários que envolvem muitas leituras e muitas atualizações, o ConcurrentDictionary<TKey, TValue> geralmente é significativamente mais rápido em computadores que tenham qualquer número de núcleos.

Em cenários que envolvem atualizações freqüentes, você pode aumentar o grau de simultaneidade na ConcurrentDictionary<TKey, TValue> e medir a para ver se o desempenho aumenta em computadores que possuem mais núcleos. Se você alterar o nível de simultaneidade, evite operações globais tanto quanto possível.

Se você só estiver lendo a chave ou valores, o Dictionary<TKey, TValue> é mais rápido porque nenhuma sincronização é necessária se o dicionário não está sendo modificado por threads.

ConcurrentBag

Em cenários de produtor-consumidor puro, System.Collections.Concurrent.ConcurrentBag<T> provavelmente irá executar mais lentamente do que a outra coleção simultânea tipos.

No misto consumidor-produtor cenários, ConcurrentBag<T> é geralmente muito mais rápido e mais escalável do que qualquer outro tipo de coleção simultâneas para pequenas e grandes cargas de trabalho.

BlockingCollection

Quando delimitadora e a semântica de bloqueio são necessários, System.Collections.Concurrent.BlockingCollection<T> provavelmente irá executar mais rápido do que qualquer implementação personalizada. Ele também suporta rich cancelamento, enumeração e manipulação de exceção.

Consulte também

Referência

System.Collections.Concurrent

Conceitos

Coleções de thread-Safe.

Programação em paralela a.NET Framework