Em circunstâncias normais, enquanto a programação multithread estiver envolvida, a complexidade do programa aumentará significativamente, o desempenho diminuirá significativamente e a probabilidade de bugs aumentará bastante.
A programação multithread tem a intenção de executar um programa em paralelo para melhorar as capacidades de processamento de dados, mas na maioria dos casos envolve competição por recursos compartilhados, então deve ser travada ao modificar objetos de recurso. No entanto, existem muitas maneiras de implementar locks, então vamos analisar a implementação e o desempenho de vários tipos de locks em C#.
Várias formas de usar fechaduras
1. Trava atômica
Alcançar a competição "sem bloqueios" por meio da operação atômica Interlocked. CompareExchange.
A explicação oficial é fornecer operações atômicas para variáveis compartilhadas por múltiplos threads. Namespace: System.Threading
2. Área crítica
A serialização de múltiplas threads para acessar recursos públicos ou um pedaço de código é rápida e adequada para controlar o acesso a dados. A sintaxe de bloqueio em C# é um açúcar sintático para a área crítica (Monitor).
3. Operação atômica
Operações atômicas, que são um caso especial, são inerentemente seguras para threads, então não há necessidade de travá-las.
Oficialmente interpretado como o incremento do valor de uma determinada variável na forma de uma operação atômica e o armazenamento do resultado. Namespace: System.Threading
4. Trava de leitura e escrita
Locks de leitura-escrita permitem ler recursos quando outros programas estão escrevendo, então, se o recurso permite leituras inúteis, isso é mais apropriado.
A explicação oficial indica um estado travado usado para gerenciar o acesso a recursos, permitindo leituras multithreaded ou acesso exclusivo de escrita. O namespace é System.Threading
5. Semáforo
Semáforos, projetados para controlar um número limitado de recursos do usuário.
A explicação oficial limita o número de threads que podem acessar um recurso ou pool de recursos ao mesmo tempo. O namespace é System.Threading
6. Eventos
Usado para notificar o tópico que alguns eventos ocorreram, iniciando o início de uma tarefa sucessora.
A explicação oficial afirma que os eventos de sincronização de threads são automaticamente resetados quando um sinal é recebido após a liberação de uma thread. Tais tipos não podem ser herdados.
7. Exclusão mútua
Existe uma classe Mutex em C#, logo abaixo do espaço nominal System.Threading, Mutex é na verdade um mutex, que não só pode lidar com a competição de recursos entre múltiplas threads, mas também lidar com a competição entre processos.
Código de teste de desempenho
Execute o código
Resultados dos testes de desempenho
Nota: Os dados acima são apenas resultado do desempenho do hardware do ambiente de teste atual e só podem ser comparados entre si.
1) Em vários testes, é definitivamente o mais rápido para não travar, então tente evitar a competição de recursos que leva à operação travada.
2) Intertravado. O CompareExchange apresenta consistentemente desempenho superior em multithreading, ficando em segundo lugar.
3) A terceira fechadura, a zona crítica, também apresenta bom desempenho, então por favor refute outros quando disserem que o desempenho da fechadura é baixo.
4) O quarto lugar é a operação de variável atômica (Atômica), mas atualmente só suporta o auto-aumento e subtração de variáveis, e a aplicabilidade não é forte.
5) O desempenho do quinto bloqueio de leitura/escrita (ReaderWriterLockSlim) também é razoável, e não suporta leitura em nada, e a praticidade ainda é relativamente boa.
6) Os semáforos, eventos e mutex restantes têm o pior desempenho, claro, têm seu próprio escopo de aplicação, mas não têm bom desempenho ao lidar com a competição de recursos.
Endereço do link original:O login do hiperlink está visível.
|