Ponto importante sobre volatile:
- A sincronização em Java é possível usando palavras
synchronized- chave volatilee bloqueios Java .
- Em Java, não podemos ter
synchronizedvariáveis. Usar synchronizedpalavra-chave com uma variável é ilegal e resultará em erro de compilação. Em vez de usar a synchronizedvariável em Java, você pode usar a volatilevariável java , que instruirá os encadeamentos da JVM a ler o valor da volatilevariável da memória principal e não a armazenará em cache localmente.
- Se uma variável não for compartilhada entre vários encadeamentos, não será necessário usar a
volatilepalavra - chave.
fonte
Exemplo de uso de volatile:
public class Singleton {
private static volatile Singleton _instance; // volatile variable
public static Singleton getInstance() {
if (_instance == null) {
synchronized (Singleton.class) {
if (_instance == null)
_instance = new Singleton();
}
}
return _instance;
}
}
Estamos criando uma instância preguiçosamente no momento em que a primeira solicitação chega.
Se não fizermos a _instancevariável volatile, o Thread que está criando a instância de Singletonnão poderá se comunicar com o outro thread. Portanto, se o Thread A está criando uma instância Singleton e logo após a criação, a CPU corrompe etc., todos os outros threads não poderão ver o valor _instancecomo não nulo e acreditam que ainda é atribuído como nulo.
Por que isso acontece? Como os threads do leitor não estão bloqueando e até que o thread do gravador saia de um bloco sincronizado, a memória não será sincronizada e o valor de _instancenão será atualizado na memória principal. Com a palavra-chave Volatile em Java, isso é tratado pelo próprio Java e essas atualizações serão visíveis por todos os threads do leitor.
Conclusão : a volatilepalavra - chave também é usada para comunicar o conteúdo da memória entre os threads.
Exemplo de uso sem volátil:
public class Singleton{
private static Singleton _instance; //without volatile variable
public static Singleton getInstance(){
if(_instance == null){
synchronized(Singleton.class){
if(_instance == null) _instance = new Singleton();
}
}
return _instance;
}
O código acima não é seguro para threads. Embora verifique novamente o valor da instância no bloco sincronizado (por motivos de desempenho), o compilador JIT pode reorganizar o bytecode de maneira que a referência à instância seja definida antes que o construtor conclua sua execução. Isso significa que o método getInstance () retorna um objeto que pode não ter sido inicializado completamente. Para tornar o código seguro para encadeamento, a palavra-chave volátil pode ser usada desde o Java 5 para a variável de instância. Variáveis marcadas como voláteis ficam visíveis apenas para outros threads quando o construtor do objeto concluir sua execução completamente.
Fonte

volatileuso em Java :
Os iteradores à prova de falhas geralmente são implementados usando um volatilecontador no objeto de lista.
- Quando a lista é atualizada, o contador é incrementado.
- Quando um
Iteratoré criado, o valor atual do contador é incorporado no Iteratorobjeto.
- Quando uma
Iteratoroperação é executada, o método compara os dois valores do contador e lança a ConcurrentModificationExceptionse eles forem diferentes.
A implementação de iteradores à prova de falhas é geralmente leve. Eles geralmente contam com propriedades das estruturas de dados da implementação de lista específica. Não há padrão geral.
volatileque veio com o novo Java Memory Model definido no JSR 133: quando um thread lê umavolatilevariável, vê não apenas o último valor gravado nele por algum outro thread, mas também todas as outras gravações em outras variáveis que eram visíveis nesse outro segmento no momento davolatilegravação. Veja esta resposta e esta referência .