Java Palavras -chave voláteis
No processamento de simultaneidade do thread java, há muita confusão no uso de uma palavra -chave volátil. Eu acho que o uso dessa palavra-chave pode fazer tudo correr bem ao usar o processamento de simultaneidade com vários threads.
O idioma Java suporta multi-threading. Para resolver o problema da simultaneidade do thread, o bloqueio síncrono e o mecanismo volátil de palavras -chave são introduzidos dentro do idioma.
sincronizado
Todos estão familiarizados com os blocos sincronizados e são implementados através da palavra -chave sincronizada. Com instruções sincronizadas e de bloco, apenas um thread pode usá-las ao mesmo tempo ao acessar multi-threads.
Método modificado sincronizado ou bloco de código.
volátil
Para variáveis modificadas com volátil, o encadeamento lerá o valor mais modificado da variável toda vez que usa a variável. O volátil é facilmente mal utilizado e usado para operações atômicas.
Vamos ver um exemplo abaixo. Implementamos um contador. Cada vez que o encadeamento inicia, o método do Counter Inc será chamado para adicionar um ao contador.
Ambiente de Execução - JDK Versão: JDK1.6.0_31, Memória: 3G CPU: X86 2.4G
public classe contador {public static int count = 0; public static void Inc () {// O atraso aqui é 1 milissegundo, tornando o resultado óbvio tentativa {thread.sleep (1); } catch (interruptedException e) {} count ++; } public static void main (string [] args) {// inicia 1000 threads ao mesmo tempo para executar cálculos i ++ e ver o resultado real para (int i = 0; i <1000; i ++) {new Thread (new Runnable () {@Override public void Run () {Counter.inc ();}}). } // O valor de cada execução aqui pode ser diferente, talvez 1000 System.out.println ("RUNIDO RUNHE: CONTA.COUNT =" + contador.Count); }}运行结果:Counter.count= 995
实际运算结果每次可能都不一样,本机的结果为:运行结果:Counter.count= 995 ,可以看出,在多线程的环境下,Counter.count并没有期望结果是1000
Muitas pessoas pensam que este é um problema de simultaneidade com vários threades. Você só precisa adicionar volatile很多人以为,这个是多线程并发问题,只需要在变量count之前加上就可以避免这个问题,那我们在修改代码看看,看看结果是不是符合我们的期望
public classe contador {public volatile static int count = 0; public static void Inc () {// O atraso aqui é 1 milissegundo, tornando o resultado óbvio tentativa {thread.sleep (1); } catch (interruptedException e) {} count ++; } public static void main (string [] args) {// inicia 1000 threads ao mesmo tempo, execute cálculos I ++ e veja o resultado real para (int i = 0; i <1000; i ++) {new Thread (new Runnable () {@Override public void () {counter.inc ();}}). } // O valor de cada execução aqui pode ser diferente, possivelmente 1000 System.out.println ("RUNIDO RUNHO: contador.Count =" + contador.count); }}Resultado em execução: contador.count = 992
O resultado da operação ainda não é tão 1000 quanto esperávamos. Vamos analisar os motivos abaixo
No artigo de coleta de lixo Java, a alocação de memória no momento da JVM é descrita. Uma das áreas de memória é a pilha de máquina virtual da JVM, e cada thread possui uma pilha de thread quando é executado.
A pilha do thread salva as informações do valor da variável durante o tempo de execução do thread. Quando um encadeamento acessar o valor de um determinado objeto, primeiro encontre o valor da variável correspondente à memória da heap através da referência do objeto e depois coloque a memória da heap
O valor específico da variável é carregado na memória local do encadeamento e uma cópia da variável é criada. Depois disso, o encadeamento não tem mais nenhum relacionamento com o valor variável do objeto na memória da heap, mas modifica diretamente o valor da variável de cópia.
Em um certo momento após a modificação (antes da saída do encadeamento), o valor da cópia da variável de encadeamento é automaticamente gravado na variável de objeto na pilha. Dessa forma, o valor do objeto na pilha mudará. A imagem a seguir
Descreva esta interação escrita
Leia e carregue variáveis de cópia da memória principal para a memória de trabalho atual
Use e atribua código de execução para alterar o valor variável compartilhado
Armazene e escreva o conteúdo da memória principal relacionada à memória com dados de memória de trabalho
onde usar e atribuir podem aparecer várias vezes
No entanto, essas operações não são atômicas, ou seja, após a carga de leitura, se a variável de contagem de memória principal for modificada, o valor na memória de trabalho do encadeamento não causará alterações correspondentes, pois foi carregada, portanto o resultado calculado será diferente do esperado.
Para variáveis modificadas por voláte
Por exemplo, se o thread 1 e o thread 2 estiverem executando operações de leitura e carga e descobrir que o valor da contagem na memória principal é 5, o valor mais recente será carregado
Depois que a contagem de heap for modificada no encadeamento 1, ela será gravada na memória principal e a variável de contagem na memória principal se tornará 6.
Como o Thread 2 já realizou a operação de leitura e carga, o valor variável da contagem principal de memória também será atualizado para 6 após a operação.
Isso faz com que a concorrência ocorra após a modificação de dois threads com a palavra -chave volátil no tempo.
Obrigado pela leitura, espero que isso possa ajudá -lo. Obrigado pelo seu apoio a este site!