Guia da palavra-chave volátil em Java
1. Visão geral
Neste artigo rápido, vamos nos concentrar em um conceito fundamental, mas muitas vezes mal compreendido, na linguagem Java - a palavra-chavevolatile.
Em Java, cada encadeamento possui um espaço de memória separado conhecido como memória de trabalho; isso mantém os valores de diferentes variáveis usadas para executar operações. Após executar uma operação, o thread copia o valor atualizado da variável para a memória principal e, a partir daí, outros threads podem ler o valor mais recente.
Simplificando, a palavra-chavevolatile marca uma variável para sempre ir para a memória principal, tanto para leituras quanto para gravações, no caso de vários threads acessando-a.
2. Quando usarvolatile
Nas situações em que o próximo valor da variável depende do valor anterior, há uma chance de que vários threads de leitura e gravação da variável fiquem fora de sincronia, devido a um intervalo de tempo entre a leitura e a gravação na memória principal. .
Isso pode ser ilustrado por um exemplo simples:
public class SharedObject {
private volatile int count = 0;
public void increamentCount() {
count++;
}
public int getCount() {
return count;
}
}
With no synchronization here, a typical race condition can occur. Basicamente, com uma lacuna de execução entre o incremento e a gravação na memória principal, outras threads podem ver um valor de 0 e tentar gravá-lo na memória principal.
A condição de corrida também pode ser evitada com o uso dos tipos de dados atômicos fornecidos pelo Java, comoAtomicInt ouAtomicLong.
3. Sincronização volátil e thread
Para todos os aplicativos multithread, precisamos garantir algumas regras para um comportamento consistente:
-
Exclusão mútua - apenas um thread executa uma seção crítica por vez
-
Visibilidade - alterações feitas por um thread nos dados compartilhados, são visíveis para outros threads para manter a consistência dos dados
Os métodos e blocosSynchronized fornecem ambas as propriedades acima, às custas do desempenho do aplicativo.
Volatile é uma primitiva bastante útil porquecan help ensure the visibility aspect of the data change, without, of course, providing the mutual exclusion. Assim, é útil em lugares onde estamos ok com vários threads executando um bloco de código em paralelo, mas precisamos garantir a propriedade de visibilidade.
4. Garantia acontece antes
Começando com Java 5, a palavra-chavevolatile também fornece recursos adicionais que garantem que os valores de todas as variáveis, incluindo variáveis não voláteis, sejam gravados na memória principal junto com a operação de gravaçãoVolatile.
Isso se chama Happens-Before, pois fornece uma visibilidade de todas as variáveis para outro segmento de leitura. Além disso, a JVM não reordena as instruções de leitura e escrita das variáveisvolatile.
Vamos dar uma olhada no exemplo:
Thread 1
object.aNonValitileVariable = 1;
object.aVolatileVariable = 100; // volatile write
Thread 2:
int aNonValitileVariable = object.aNonValitileVariable;
int aVolatileVariable = object.aVolatileVariable;
Nesse caso, quandoThread 1 escreveu o valor deaVolatileVariable, o valor deaNonValitileVariable também é gravado na memória principal. And even though it’s not a volatile variable, it is exhibiting a volatile behavior.
Fazendo uso dessa semântica, podemos definir apenas algumas das variáveis em nossa classe comovolatilee otimizar a garantia de visibilidade.
5. Conclusão
Neste tutorial, exploramos mais sobre a palavra-chavevolatile e seus recursos, bem como as melhorias feitas a partir do Java 5.
Como sempre, os exemplos de código podem ser encontradosover on GitHub.