A palavra-chave volatile em Java é usada para marcar uma variável como sendo armazenada na memória principal, em vez de apenas no cache da thread. Isso significa que todas as threads que acessarem a variável terão sempre o valor mais recente, evitando inconsistências quando a variável é acessada simultaneamente por várias threads.
O Problema do Cache nas Threads
Em Java, cada thread pode armazenar variáveis em cache para melhorar o desempenho. Isso pode causar problemas quando várias threads acessam e modificam uma variável compartilhada. A palavra-chave volatile garante que a variável seja lida e escrita diretamente na memória principal, garantindo visibilidade entre threads.
Sintaxe
public class ExemploVolatile {
private volatile boolean ativo = true;
public void executar() {
while (ativo) {
// Lógica do programa
}
}
public void parar() {
ativo = false; // Atualiza a variável
}
}
Posts recentes
Funcionamento do volatile
- Visibilidade entre Threads: Quando uma variável é marcada como volatile, as threads sempre lerão seu valor diretamente da memória principal e não de um cache local. Isso garante que mudanças feitas por uma thread estejam visíveis para outras threads.
- Sem Cache: O valor da variável volatile nunca será armazenado em cache pelas threads, o que evita que elas trabalhem com uma cópia desatualizada.
Exemplo de Uso
public class ExemploVolatile {
private volatile boolean ativo = true;
public void executar() {
System.out.println("Thread iniciada...");
while (ativo) {
// Código de execução contínua
}
System.out.println("Thread encerrada.");
}
public void parar() {
ativo = false; // Atualiza o valor, que será visível para todas as threads
}
public static void main(String[] args) {
ExemploVolatile exemplo = new ExemploVolatile();
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
exemplo.executar();
}
});
t1.start();
try {
Thread.sleep(2000); // Aguarda 2 segundos antes de parar a execução
} catch (InterruptedException e) {
e.printStackTrace();
}
exemplo.parar(); // Modifica a variável para false, parando a execução da thread
}
}
Neste exemplo:
- A variável ativo é marcada como volatile para garantir que todas as threads tenham acesso ao valor mais atualizado.
- Uma thread executa o método executar, que continua rodando enquanto a variável ativo for true.
- Após 2 segundos, o método parar é chamado, o que define a variável ativo como false e faz a thread parar.
Limitações do volatile
- Não Garante Sincronização Completa: O volatile apenas garante visibilidade entre threads, mas não é suficiente para operações atômicas ou para garantir exclusão mútua (mutex). Se várias threads precisarem modificar uma variável de forma concorrente, será necessário usar outras técnicas, como blocos sincronizados (synchronized).
- Leitura e Escrita Simples: O volatile só é útil para operações simples de leitura e escrita. Para operações mais complexas, como incrementar uma variável, é melhor usar classes atômicas como AtomicInteger.
Resumo
- volatile garante que uma variável seja sempre lida e escrita na memória principal, assegurando a visibilidade entre threads.
- É útil em cenários onde várias threads precisam acessar e modificar o valor de uma variável de forma consistente.
- Não substitui blocos sincronizados (synchronized) ou outras técnicas para garantir atomicidade em operações mais complexas.