Este artigo é um artigo espelhado de tradução automática, por favor clique aqui para ir para o artigo original.

Vista: 46741|Resposta: 7

[Fonte] Volátil vs. Intertravado vs. travado

[Copiar link]
Publicado em 27/08/2018 14:40:35 | | |
Digamos que exista uma classe que contenha um campo contador público de int que pode ser acessado por múltiplos threads, e esse número só vai aumentar ou diminuir.

Ao adicionar esse campo, qual dos seguintes esquemas deve ser usado e por quê?

  • lock(this.locker) this.counter++;
  • Interlocked.Increment(ref this.counter);
  • Mude o modificador de acesso de contador para volátil público


Pior (nenhum deles realmente funciona)

Mude o modificador de acesso de contador para volátil público

Essa abordagem na verdade não é segura, e o ponto sobre o volátil é que múltiplas threads rodando em múltiplas CPUs armazenam dados em buffer e reorganizam instruções executadas.

Se for não volátil, quando a CPU A aumenta em um valor, a CPU B precisa esperar um pouco para ver o valor aumentado, o que pode causar problemas.

Se for volátil, garante que ambos os CPUs vejam o mesmo valor ao mesmo tempo. Mas isso não evita operações de leitura e escrita que se cruzam.

Adicionar valor a uma variável na verdade leva três etapas

1. Leitura, 2. Adicionar 3. Escrever

Suponha que a thread A leia o valor do contador como 1 e não esteja pronta para aumentar, então a thread B também leia o valor do contador como 1, e então ambas as threads começam a realizar operações incrementais e de escrita. O valor do marcador final é 2. Isso não está certo, ambas as threads fizeram uma operação de aumento, e o resultado correto deveria ser 3. Portanto, rotulá-lo como volátil é simplesmente inseguro.

É melhor

lock(this.locker) this.counter++;

Assim fica seguro (lembre-se de trancar todos os lugares que quiser acessar esse balcão, claro). Isso impede que qualquer outra thread execute o código bloqueado. E também previne o problema de sequenciamento de instruções multi-CPU mencionado acima. O problema é que o lock tem desempenho lento, e se você usar o lock em outros lugares não relacionados, ele pode bloquear suas outras threads.

Melhores

Interlocked.Increment(ref this.counter);

Isso é seguro e muito eficiente. Ele realiza leitura, aumento, gravação de três operações em um átomo sem ser interrompido no meio. Como não afeta outros códigos, você não precisa lembrar das fechaduras em outros lugares. E também é muito rápido (como diz o MSDN, nos processadores de hoje, geralmente é só uma instrução).

Mas não tenho certeza se isso também resolve o problema de ordenação de instruções da CPU, ou se precisa ser usado em conjunto com o volátil e esse incremento.

Suplemento: Quais problemas voláteis resolve bem?

Como o volátil não pode impedir o multithreading, o que ele pode fazer? Um bom exemplo é que você tem dois threads, um sempre escreve para uma variável, digamos que essa variável seja queneLength, e o outro sempre lê dados dessa variável. Se o comprimento da fila não for volátil, a thread A pode ser lida 5 vezes, mas a thread B pode apresentar dados atrasados, ou até mesmo dados na ordem errada. Uma solução é usar o bloqueio, mas nesse caso você também pode usar volátil. Isso garante que a thread B sempre veja os dados mais recentes escritos pela thread A, mas essa lógica só funciona se você não ler quando escreve, e se não escrever na hora de ler. Quando múltiplas threads querem fazer operações de leitura-modificação-escrita, você precisa usar Interlock ou lock.





Anterior:Método de criptografia Java MD5
Próximo:O Linq implementa consultas condicionais não em e em SQL
Publicado em 29/08/2018 16:21:42 |
Olá, o código que você fez antes que combina highcharts, histogramas empilhados e histogramas perfuráveis? Gostaria de perguntar se você pode enviar um código que possa ser editado na interface https://jshare.com.cn/demos/hhhhDz?hc-theme=grid-light?
Publicado em 29/08/2018 16:22:13 |
Toda a rede é apenas seu recurso.
Publicado em 29/08/2018 16:22:55 |
Porque os 90 anos anteriores não podiam deixar recado. Então
Publicado em 29/08/2018 16:40:40 |
É conveniente adicionar uma informação de contato? Consultar você
 Senhorio| Publicado em 15/09/2018 13:10:16 |
private static int safeInstanceCount = 0; Operar com átomos
System.Threading.Interlocked.Increment(ref safeInstanceCount); Auto-aumento 1
System.Threading.Interlocked.Decrement(ref safeInstanceCount); Auto-menos 1
Publicado em 21/05/2020 16:43:54 |
Apoie o dono para compartilhar
 Senhorio| Publicado em 11/06/2020 15:00:16 |
1. Conceito

Em um ambiente multithreaded, operações que não são interrompidas por mecanismos de escalonamento de threads; Uma vez que essa operação começa, ela roda até o fim, sem nenhuma troca de contexto (trocar para outro thread) entre elas.

2. Classe

Classe estática System.Threading.Interlocked

3. Funções comumente usadas (veja o restante)

1. estática pública int Decrement(ref int location); Reduza o valor da variável especificada na forma de uma operação atômica e armazene o resultado

Equivalente a lock(obj){i--; }

2. estática pública int Incremento (ref int location); Incremente o valor da variável especificada na forma de uma operação atômica e armazene o resultado

Equivalente a lock(obj){i++; }
Disclaimer:
Todo software, material de programação ou artigos publicados pela Code Farmer Network são apenas para fins de aprendizado e pesquisa; O conteúdo acima não deve ser usado para fins comerciais ou ilegais, caso contrário, os usuários terão todas as consequências. As informações deste site vêm da Internet, e disputas de direitos autorais não têm nada a ver com este site. Você deve deletar completamente o conteúdo acima do seu computador em até 24 horas após o download. Se você gosta do programa, por favor, apoie um software genuíno, compre o registro e obtenha serviços genuínos melhores. Se houver qualquer infração, por favor, entre em contato conosco por e-mail.

Mail To:help@itsvse.com