volatile
possui semântica para visibilidade da memória. Basicamente, o valor de um volatile
campo se torna visível a todos os leitores (outros threads em particular) após a conclusão de uma operação de gravação. Sem volatile
, os leitores poderiam ver algum valor não atualizado.
Para responder sua pergunta: Sim, eu uso uma volatile
variável para controlar se algum código continua um loop. O loop testa o volatile
valor e continua, se for true
. A condição pode ser configurada false
chamando um método "stop". O loop vê false
e termina quando testa o valor após o método stop concluir a execução.
O livro " Concorrência Java na Prática ", que eu recomendo, fornece uma boa explicação volatile
. Este livro foi escrito pela mesma pessoa que escreveu o artigo da IBM mencionado na pergunta (na verdade, ele cita seu livro na parte inferior desse artigo). Meu uso volatile
é o que o artigo chama de "sinalizador de status padrão 1".
Se você quiser aprender mais sobre como volatile
funciona sob o capô, leia o modelo de memória Java . Se você quiser ir além desse nível, consulte um bom livro de arquitetura de computadores como Hennessy & Patterson e leia sobre a coerência e a consistência do cache.
volatile
que veio com o novo Java Memory Model definido no JSR 133: quando um thread lê umavolatile
variá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 davolatile
gravação. Veja esta resposta e esta referência ."... o modificador volátil garante que qualquer thread que leia um campo veja o valor gravado mais recentemente." - Josh Bloch
Se você está pensando em usar
volatile
, leia o pacotejava.util.concurrent
que trata do comportamento atômico.A publicação da Wikipedia sobre um padrão Singleton mostra uso volátil.
fonte
volatile
-synchronized
chave e ambos ?volatile
exemplo. Pode ser encontrado em uma versão arquivada .void
-public
chave e ambos ".Ponto importante sobre
volatile
:synchronized
- chavevolatile
e bloqueios Java .synchronized
variáveis. Usarsynchronized
palavra-chave com uma variável é ilegal e resultará em erro de compilação. Em vez de usar asynchronized
variável em Java, você pode usar avolatile
variável java , que instruirá os encadeamentos da JVM a ler o valor davolatile
variável da memória principal e não a armazenará em cache localmente.volatile
palavra - chave.fonte
Exemplo de uso de
volatile
:Estamos criando uma instância preguiçosamente no momento em que a primeira solicitação chega.
Se não fizermos a
_instance
variávelvolatile
, o Thread que está criando a instância deSingleton
nã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_instance
como 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
_instance
nã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.Exemplo de uso sem volátil:
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
volatile
uso em Java :Os iteradores à prova de falhas geralmente são implementados usando um
volatile
contador no objeto de lista.Iterator
é criado, o valor atual do contador é incorporado noIterator
objeto.Iterator
operação é executada, o método compara os dois valores do contador e lança aConcurrentModificationException
se 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.
fonte
private static final Singleton _instance;
também.volatile
é muito útil para interromper threads.Não que você deva escrever seus próprios encadeamentos, o Java 1.6 possui muitos conjuntos de encadeamentos agradáveis. Mas se você tiver certeza de que precisa de um thread, precisará saber como interrompê-lo.
O padrão que eu uso para threads é:
No segmento de código acima, a leitura do thread
close
no loop while é diferente daquela que chamaclose()
. Sem volátil, o encadeamento que executa o loop pode nunca ver a alteração fechar.Observe como não há necessidade de sincronização
fonte
volatile
palavra - chave, e sempre parece funcionar bem.Um exemplo comum de uso
volatile
é usar umavolatile boolean
variável como um sinalizador para finalizar um encadeamento. Se você iniciou um encadeamento e deseja interrompê-lo com segurança de um encadeamento diferente, pode fazer com que o encadeamento verifique periodicamente um sinalizador. Para pará-lo, defina o sinalizador como true. Ao fazer o sinalizadorvolatile
, você pode garantir que o encadeamento que o está verificando seja definido na próxima vez que o verificar sem precisar usar umsynchronized
bloco.fonte
Uma variável declarada com
volatile
palavra - chave tem duas qualidades principais que a tornam especial.Se tivermos uma variável volátil, ela não poderá ser armazenada em cache na memória cache do computador (microprocessador) por qualquer thread. O acesso sempre acontecia na memória principal.
Se houver uma operação de gravação em uma variável volátil e, de repente, uma operação de leitura for solicitada, é garantido que a operação de gravação será concluída antes da operação de leitura .
Duas qualidades acima deduzem que
E por outro lado,
volatile
palavra-chave é a maneira ideal de manter uma variável compartilhada que possui 'n' número de threads de leitor e apenas um thread de escritor para acessá-lo. Depois de adicionar avolatile
palavra-chave, ela está pronta. Nenhuma outra sobrecarga sobre segurança de rosca.Inversamente,
Não podemos usar a
volatile
palavra-chave apenas para satisfazer uma variável compartilhada que tenha mais de um segmento de gravador acessando-a .fonte
Ninguém mencionou o tratamento da operação de leitura e gravação para o tipo variável longa e dupla. Leituras e gravações são operações atômicas para variáveis de referência e para a maioria das variáveis primitivas, exceto para tipos de variáveis longas e duplas, que devem usar a palavra-chave volátil para serem operações atômicas. @ligação
fonte
Sim, o volátil deve ser usado sempre que você desejar que uma variável mutável seja acessada por vários encadeamentos. Não é um caso de uso muito comum, porque normalmente é necessário executar mais de uma única operação atômica (por exemplo, verificar o estado da variável antes de modificá-lo); nesse caso, você usaria um bloco sincronizado.
fonte
Na minha opinião, dois cenários importantes, além de interromper o encadeamento no qual a palavra-chave volátil é usada, são:
fonte
Você precisará usar a palavra-chave 'volátil' ou 'sincronizado' e quaisquer outras ferramentas e técnicas de controle de simultaneidade que possa ter à sua disposição se estiver desenvolvendo um aplicativo multithread. Exemplo desse aplicativo são aplicativos de desktop.
Se você estiver desenvolvendo um aplicativo que seria implantado no servidor de aplicativos (Tomcat, JBoss AS, Glassfish, etc), não precisará lidar com o controle de simultaneidade, como já foi abordado pelo servidor de aplicativos. De fato, se eu me lembrei corretamente, o padrão Java EE proíbe qualquer controle de simultaneidade em servlets e EJBs, pois faz parte da camada de 'infraestrutura' que você deveria estar livre de manipulá-lo. Você só controla a simultaneidade nesse aplicativo se estiver implementando objetos singleton. Isso já foi abordado se você tricotar seus componentes usando o frameworkd, como o Spring.
Portanto, na maioria dos casos de desenvolvimento Java em que o aplicativo é um aplicativo da Web e usando a estrutura de IoC como Spring ou EJB, você não precisaria usar 'volátil'.
fonte
volatile
garante apenas que todos os threads, até eles mesmos, estão aumentando. Por exemplo: um contador vê a mesma face da variável ao mesmo tempo. Não é usado em vez de coisas sincronizadas ou atômicas ou outras coisas, faz completamente as leituras sincronizadas. Por favor, não o compare com outras palavras-chave java. Como o exemplo mostra abaixo, as operações variáveis voláteis também são atômicas e fracassam ou são bem-sucedidas ao mesmo tempo.Mesmo se você colocar resultados voláteis ou não, sempre será diferente. Mas se você usar AtomicInteger, os resultados abaixo serão sempre os mesmos. O mesmo ocorre com os sincronizados.
fonte
Sim, eu uso bastante - pode ser muito útil para código multiencadeado. O artigo que você apontou é bom. Embora haja duas coisas importantes a serem lembradas:
fonte
Cada encadeamento que acessa um campo volátil lê seu valor atual antes de continuar, em vez de (potencialmente) usar um valor em cache.
Somente variável de membro pode ser volátil ou transitória.
fonte
Absolutamente sim. (E não apenas em Java, mas também em C #.) Há momentos em que você precisa obter ou definir um valor que é garantido como uma operação atômica em sua plataforma, um int ou booleano, por exemplo, mas não exige a sobrecarga do bloqueio da linha. A palavra-chave volátil permite garantir que, ao ler o valor, você obtenha o valor atual e não um valor em cache que tenha sido tornado obsoleto por uma gravação em outro encadeamento.
fonte
Existem dois usos diferentes de palavras-chave voláteis.
Um sinalizador de ocupado é usado para impedir que um encadeamento continue enquanto o dispositivo está ocupado e o sinalizador não está protegido por um bloqueio:
O segmento de teste continuará quando outro segmento desativar o sinalizador de ocupado :
No entanto, como ocupado é acessado com freqüência no encadeamento de teste, a JVM pode otimizar o teste colocando o valor de ocupado em um registro e, em seguida, teste o conteúdo do registro sem ler o valor de ocupado na memória antes de cada teste. O encadeamento de teste nunca veria mudança ocupada e o outro encadeamento alteraria apenas o valor de ocupado na memória, resultando em conflito. Declarar o sinalizador de ocupado como volátil força seu valor a ser lido antes de cada teste.
O uso de variáveis voláteis reduz o risco de erros de consistência da memória , porque qualquer gravação em uma variável volátil estabelece um relacionamento "acontece antes" com leituras subsequentes dessa mesma variável. Isso significa que as alterações em uma variável volátil são sempre visíveis para outros threads.
A técnica de ler, escrever sem erros de consistência de memória é chamada de ação atômica .
Uma ação atômica é aquela que efetivamente acontece ao mesmo tempo. Uma ação atômica não pode parar no meio: ou acontece completamente ou não acontece. Nenhum efeito colateral de uma ação atômica é visível até que a ação seja concluída.
Abaixo estão as ações que você pode especificar que são atômicas:
Felicidades!
fonte
Volátil faz o seguinte.
1> A leitura e gravação de variáveis voláteis por diferentes threads são sempre da memória, não do cache ou do registro da própria CPU do thread. Portanto, cada thread lida sempre com o valor mais recente. 2> Quando 2 threads diferentes trabalham com a mesma instância ou variáveis estáticas no heap, um pode ver as ações de outros como fora de ordem. Veja o blog de jeremy manson sobre isso. Mas volátil ajuda aqui.
O código a seguir em execução mostra como vários threads podem ser executados em ordem predefinida e imprimir saídas sem usar a palavra-chave sincronizada.
Para conseguir isso, podemos usar o seguinte código de execução completo.
O link a seguir no github possui um leia-me, que fornece uma explicação adequada. https://github.com/sankar4git/volatile_thread_ordering
fonte
volatile
diz para um programador que o valor sempre estará atualizado. O problema é que o valor pode ser salvo em diferentes tipos de memória de hardware. Por exemplo, podem ser registros da CPU, cache da CPU, RAM ... Os registros da CPU e o cache da CPU pertencem à CPU e não podem compartilhar dados diferentes da RAM que estão sendo resgatados no ambiente de multithreadingvolatile
A palavra-chave diz que uma variável será lida e gravada diretamente da / para a memória RAM . Tem alguma pegada de computaçãoJava 5
estendidovolatile
apoiandohappens-before
[Sobre]volatile
A palavra-chave não cura umarace condition
situação em que vários encadeamentos podem gravar alguns valores simultaneamente. A resposta ésynchronized
palavra - chave [Sobre]Como resultado, segurança somente quando um thread grava e outros apenas leem o
volatile
valorvolátil vs sincronizado
fonte
Na página de documentação da Oracle , surge a necessidade de variável volátil para corrigir problemas de consistência da memória:
Isso significa que as alterações em uma
volatile
variável são sempre visíveis para outros threads. Isso também significa que, quando um thread lê uma variável volátil, ele vê não apenas as alterações mais recentes novolatile
, mas também os efeitos colaterais do código que levou à alteração.Conforme explicado na
Peter Parker
resposta, na ausência devolatile
modificador, a pilha de cada thread pode ter sua própria cópia da variável. Ao fazer a variável comovolatile
, os problemas de consistência da memória foram corrigidos.Dê uma olhada na página do tutorial de jenkov para entender melhor.
Dê uma olhada na pergunta SE relacionada para obter mais detalhes sobre casos voláteis e de uso para usar voláteis:
Diferença entre volátil e sincronizado em Java
Um caso de uso prático:
Você tem muitos segmentos, que precisam imprimir o tempo atual em um formato específico, por exemplo:
java.text.SimpleDateFormat("HH-mm-ss")
. Você pode ter uma classe, que converte o tempo atual emSimpleDateFormat
e atualiza a variável a cada segundo. Todos os outros threads podem simplesmente usar essa variável volátil para imprimir o horário atual nos arquivos de log.fonte
Variáveis voláteis são sincronização leve. Quando a visibilidade dos dados mais recentes entre todos os encadeamentos é requisito e a atomicidade pode ser comprometida, nessas situações as Variáveis Voláteis devem ser preferidas. A leitura de variáveis voláteis sempre retorna as gravações mais recentes feitas por qualquer encadeamento, pois elas não são armazenadas em cache em registradores nem em caches onde outros processadores não podem ver. Volátil é sem bloqueio. Eu uso volátil, quando o cenário atende aos critérios mencionados acima.
fonte
A chave volátil, quando usada com uma variável, garantirá que os threads que lêem essa variável tenham o mesmo valor. Agora, se você tiver vários threads lendo e gravando em uma variável, tornar a variável volátil não será suficiente e os dados serão corrompidos. As threads de imagem leram o mesmo valor, mas cada uma delas realizou algumas alterações (por exemplo, um contador incrementado). Ao gravar de volta na memória, a integridade dos dados é violada. É por isso que é necessário sincronizar a variável (diferentes maneiras são possíveis)
Se as alterações forem feitas por 1 thread e os outros precisarem apenas ler esse valor, o volátil será adequado.
fonte
A variável volátil é basicamente usada para atualização instantânea (liberação) na linha principal de cache compartilhado, uma vez atualizada, para que as alterações sejam refletidas em todos os threads de trabalho imediatamente.
fonte
Abaixo está um código muito simples para demonstrar o requisito da
volatile
variável for usada para controlar a execução do Thread a partir de outro thread (este é um cenário em quevolatile
é necessário).Quando
volatile
não é usado: você nunca verá a mensagem ' Parado em: xxx ', mesmo depois de ' Parando em: xxx ', e o programa continua em execução.Quando
volatile
usado: você verá o ' Interrompido: xxx ' imediatamente.Demonstração: https://repl.it/repls/SilverAgonizingObjectcode
fonte