"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 |
---|---|---|
|
|
Passo 1. O valor da variável count é copiado da memória global para um registrador do processador. Etapa 2. Etapa 3. |
"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 |
---|---|---|
|
|
|
"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."