"Olá, amigo!"

"Oi, Ellie!"

"Quero falar sobre o modificador volátil. Você sabe o que é isso?"

"Algo a ver com fios. Não me lembro exatamente."

"Então escute. Aqui estão alguns detalhes técnicos para você:"

"Um computador tem dois tipos de memória: memória global (comum) e memória embutida no processador. A memória embutida do processador é dividida em registradores, cache de primeiro nível (L1), cache de segundo nível (L2) e terceiro nível (L3)."

"Esses tipos de memória têm velocidades diferentes. A memória mais rápida e menor são os registradores, depois o cache do processador (L1, L2, L3) e, finalmente, a memória global (a mais lenta)."

"A memória global e o cache do processador operam em velocidades totalmente diferentes, de modo que a máquina Java permite que cada thread armazene as variáveis ​​usadas com mais frequência na memória do thread local (no cache do processador)."

"Esse processo pode ser controlado de alguma forma?"

"Na verdade, não. Todo o trabalho é feito pela máquina Java. É muito inteligente quando se trata de otimizar o desempenho."

"Mas é por isso que estou dizendo isso. Há um pequeno problema. Quando dois threads estão trabalhando com a mesma variável, cada um pode armazenar uma cópia em seu próprio cache local. E então um thread pode alterar a variável, mas o segundo pode não ver a mudança, porque ainda está trabalhando com sua própria cópia da variável."

"Bem, o que pode ser feito então?"

"Os criadores do Java forneceram uma palavra-chave especial para esta situação: volátil. Se uma variável é acessada de diferentes threads, você precisa marcá-la com o modificador volátil, para que a máquina Java não a coloque no cache. É assim que costuma ser visual:"

public volatile int count = 0;

"Oh, eu me lembro. Você já mencionou isso. Eu já sei disso."

"Claro que sim. Mas você só se lembrou quando eu contei."

"Er, bem, eu esqueci um pouco."

"A repetição é a mãe do aprendizado!"

"Aqui estão alguns fatos novos sobre o modificador volátil. O modificador volátil apenas garante que a variável será lida e gravada com segurança. Não garante que será alterada com segurança."

"Qual é a diferença?"

"Veja como a variável é alterada:"

Código O que realmente acontece: Descrição
count++
register = count;

register = register+1;

count = register;
Passo 1.
O valor da variável count é copiado da memória global para um registrador do processador.

Etapa 2.
Dentro do processador, a variável de registro é incrementada em 1.

Etapa 3.
O valor da variável é copiado do processador para a memória global.

"Nossa! Então, todas as variáveis ​​são alteradas apenas no processador?"

"Sim."

"E os valores são copiados de um lado para o outro: da memória para o processador e vice-versa?"

"Sim."

"O modificador volátil garante que quando a variável count for acessada ela será lida da memória (passo 1). E se uma thread quiser atribuir um novo valor, com certeza ele estará na memória global (passo 3)."

"Mas a máquina Java não garante que não haverá troca de thread entre as etapas 1 e 3."

"Então, incrementar a variável em 1 é na verdade três operações?"

"Sim."

"E se duas threads simultaneamente quiserem executar count++, elas podem interferir uma na outra?"

"Sim, confira:"

Tópico 1 Tópico 2 Resultado
register1 = count;
register1++;
count = register1;
register2 = count;
register2++;
count = register2;
register1 = count;
register2 = count;
register2++;
count = register2;
register1++;
count = register1;

"Então, você pode acessar a variável, mas alterá-la ainda é arriscado?"

"Bem, você pode mudar, apenas tome cuidado ☺"

"Como?"

" sincronizado  é nosso melhor amigo."

"Eu vejo."