Na programação multi-thread Java, é frequentemente encontrado volátil. Às vezes, essa palavra -chave é frequentemente confundida com sincronizado ou bloqueado. A análise específica é a seguinte:
Em um ambiente multithread, haverá um problema de visibilidade das variáveis de membros: cada encadeamento no Java possui um espaço de memória de uma pilha de threads, que salva as informações variáveis do thread quando estiver em execução. Quando um thread acessa um determinado valor variável, primeiro encontrará a memória da heap do objeto ou o conteúdo específico da pilha (tipo de dados nativo) com base no endereço da variável e, em seguida, salve a mesma cópia de valor na pilha de threads deste thread. Em seguida, todas as operações nessa variável não têm nada a ver com o conteúdo variável na pilha antes que o thread saia. Ele opera na cópia na pilha de threads. Após a conclusão da operação, o resultado da operação será gravado de volta à memória principal. Se houver dois threads A e B, e os colegas operam uma certa variável x; A adiciona 1 a x, então a cópia obtida por b pode ser o resultado de x mais 1 ou x; Para garantir que a mais recente variável de dados na memória seja necessária para adicionar a palavra -chave volátil; portanto, toda vez que você opera em x, você verificará se o valor da variável na pilha de encadeamento é o mesmo que o valor da variável na memória e, se for diferente, será carregado novamente.
por exemplo:
public class Threadsee {// O thread T1 executará operações correspondentes com base no valor do sinalizador, e o encadeamento principal alterará o valor de T1 public static void main (string [] args) lança interruptedException {threadTest th = new ThreadTest (); Thread t1 = novo thread (th); t1.start (); Thread.sleep (1000); th.ChangeFlag (); Thread.sleep (2000); System.out.println (th.getflag ()); }} class ThreadTest implementa Runnable {// Quando um thread acessa uma variável, ele a carrega na pilha de threads correspondente. Cada operação, deve obter os dados mais recentes na memória privada volátil booleana stopflag; @Override public void run () {int i = 0; while (! Stopflag) {i ++; System.out.println ("=="+Thread.currentThread (). GetName ()); } System.out.println ("Treque acabamento:"+i); } public void changeflag () {this.stopflag = true; System.out.println (thread.currentThread (). GetName ()+"***********"); } public boolean getFlag () {return stopflag; }} Se o código acima for removido, ele continuará sendo executado em um loop morto.
Mas o volátil não pode garantir a sincronização segura para roscas
por exemplo:
classe pública threadsave implementa runnable {static shreadSave Sync = new ThreadSave (); estático volátil int j = 0; // bloqueio de bloqueio = new reentrantlock (); public void inscane () {// Lock.lock (); for (int i = 0; i <10000000; i ++) {j ++; } // Lock.unlock (); } @Override public void run () {inscane (); } public static void main (string [] args) lança interruptedException {thread t1 = novo thread (sincronização); Thread T2 = novo thread (sincronização); t1.start (); t2.start (); t1.Join (); t2.Join (); System.out.println (j); }} O resultado da execução de acordo com o código acima não deve ser de 20000000,
Porque, para variáveis modificadas por volátil, a máquina virtual da JVM garante apenas que o valor carregado da memória principal para a memória de trabalho do encadeamento seja a mais recente.
Por exemplo, se o thread 1 e o thread 2 estiverem executando pilha de threads e operações de leitura e carga da memória principal e descobrir que o valor da contagem na memória principal é 5, o valor mais recente será carregado. Depois que a contagem de heap Thread 1 for modificada, 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 operações de leitura e carga, após a execução da operação, o valor variável da contagem de memória principal também será atualizado para 6;
Isso faz com que a concorrência ocorra após a modificação de dois threads com a palavra -chave volátil no tempo.
Resumindo:
A Volatile apenas garantirá que o encadeamento faça uma ação que verifique se o valor variável da pilha de encadeamento atual é o mesmo que o valor dos dados na memória principal, tudo isso. O bloqueio ou sincronizado garantirá que apenas um único encadeamento entre no método em um certo momento, garantindo assim a segurança do encadeamento.
Portanto, se vários threads modificarem uma variável volátil, não há significado lógico real. Se um encadeamento modificar o valor variável de outros threads que dependem da modificação, será útil no momento.
O exposto acima é tudo sobre este artigo, espero que seja útil para o aprendizado de todos.