É correto dizer que static
significa uma cópia do valor para todos os objetos e volatile
significa uma cópia do valor para todos os segmentos?
De qualquer forma, um static
valor variável também será um valor para todos os encadeamentos, então por que devemos procurar volatile
?
Respostas:
Declarar uma variável estática em Java significa que haverá apenas uma cópia, não importa quantos objetos da classe sejam criados. A variável estará acessível mesmo sem a
Objects
criação. No entanto, os threads podem ter valores armazenados em cache localmente.Quando uma variável é volátil e não estática , haverá uma variável para cada
Object
. Portanto, aparentemente não há diferença de uma variável normal, mas totalmente diferente da estática . No entanto, mesmo comObject
campos, um encadeamento pode armazenar em cache um valor variável localmente.Isso significa que se dois encadeamentos atualizam uma variável do mesmo objeto simultaneamente e a variável não é declarada volátil, pode haver um caso em que um dos encadeamentos tenha em cache um valor antigo.
Mesmo se você acessar um valor estático através de vários threads, cada thread poderá ter sua cópia em cache local! Para evitar isso, você pode declarar a variável como estática volátil e isso forçará o thread a ler cada vez que o valor global.
No entanto, volátil não substitui a sincronização adequada!
Por exemplo:
A execução
concurrentMethodWrong
simultânea muitas vezes pode levar a um valor final de contador diferente de zero!Para resolver o problema, você precisa implementar um bloqueio:
Ou use a
AtomicInteger
classe.fonte
Diferença entre estático e volátil:
Variável estática : se dois Threads (suponha
t1
et2
) estão acessando o mesmo objeto e atualizando uma variável declarada como estática, isso significat1
et2
podem fazer sua própria cópia local do mesmo objeto (incluindo variáveis estáticas) em seu respectivo cache, portanto atualize feito pelat1
variável estática em seu cache local não refletirá na variável estática dot2
cache.As variáveis estáticas são usadas no contexto de Objeto, onde a atualização feita por um objeto refletirá em todos os outros objetos da mesma classe, mas não no contexto de Thread, em que a atualização de um thread na variável estática refletirá as alterações imediatamente em todos os objetos. threads (no cache local).
Variável volátil : se dois Threads (suponha
t1
et2
) estão acessando o mesmo objeto e atualizando uma variável que é declarada como volátil, isso significat1
et2
pode fazer seu próprio cache local do Objeto, exceto a variável que é declarada como volátil . Portanto, a variável volátil terá apenas uma cópia principal que será atualizada por diferentes threads e a atualização feita por um thread na variável volátil será refletida imediatamente no outro Thread.fonte
volatile
variável pode ser compartilhada entre caches de CPU distintos. Isso não apresenta problema porque o cache negocia a propriedade exclusiva da linha de cache antes de modificá-lo.Além de outras respostas, gostaria de adicionar uma imagem para ela (a foto facilita a compreensão)
static
variáveis podem ser armazenadas em cache para threads individuais. No ambiente multithread, se um thread modificar seus dados em cache, isso pode não refletir em outros threads, pois eles têm uma cópia deles .volatile
A declaração garante que os threads não armazenem em cache os dados e use apenas a cópia compartilhada .fonte da imagem
fonte
Eu penso
static
evolatile
não tenho nenhuma relação. Eu sugiro que você leia o tutorial em java para entender o Acesso Atômico , e por que usar o acesso atômico, entender o que está intercalado , você encontrará a resposta.fonte
Em termos simples,
static : as
static
variáveis estão associadas à classe , e não a qualquer objeto . Cada instância da classe compartilha uma variável de classe, que está em um local fixo na memóriavolátil : esta palavra-chave é aplicável a variáveis de classe e instância .
Dê uma olhada neste artigo por
Javin Paul
entender variáveis voláteis em uma maneira melhor.Na ausência de
volatile
palavra-chave, o valor da variável na pilha de cada thread pode ser diferente. Fazendo a variável comovolatile
, todos os threads obterão o mesmo valor em sua memória de trabalho e erros de consistência de memória foram evitados.Aqui, o termo
variable
pode serstatic
variável (classe) ou variávelinstance
(objeto).Em relação à sua consulta:
Se eu precisar de
instance
variável no meu aplicativo, não posso usar astatic
variável. Mesmo no caso destatic
variável, a consistência não é garantida devido ao cache do Thread, conforme mostrado no diagrama.O uso de
volatile
variáveis reduz o risco de erros de consistência da memória, porque qualquer gravação em uma variável volátil estabelece um relacionamento de antes do acontecimento 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.Usar o acesso simples a variáveis atômicas é mais eficiente do que acessar essas variáveis por meio de código sincronizado
Algumas das classes no
java.util.concurrent
pacote fornecem métodos atômicos que não dependem da sincronização.Consulte este artigo de controle de simultaneidade de alto nível para obter mais detalhes.
Dê uma olhada especialmente nas variáveis atômicas .
Perguntas relacionadas ao SE:
Volatile Vs Atomic
AtomicBoolean vs Volatile boolean
Diferença entre volátil e sincronizado em Java
fonte
volatile
anterior, mas, esta resposta me esclarece muito por que ainda preciso usarvolatile
com astatic
variávelo acesso a valores variáveis voláteis será direto da memória principal. Ele deve ser usado apenas em ambientes com vários threads. A variável estática será carregada uma vez. Se for usado no ambiente de thread único, mesmo que a cópia da variável seja atualizada e não haverá danos ao acessá-lo, pois há apenas um thread.
Agora, se a variável estática for usada no ambiente com vários threads, haverá problemas se alguém esperar o resultado desejado. Como cada encadeamento possui sua própria cópia, qualquer incremento ou decréscimo na variável estática de um encadeamento pode não refletir em outro encadeamento.
se se espera resultados desejados da variável estática, use volátil com estática no multi-threading, tudo será resolvido.
fonte
Não tenho certeza se as variáveis estáticas estão armazenadas em cache na memória local do encadeamento ou NÃO. Mas quando eu executei dois threads (T1, T2) acessando o mesmo objeto (obj) e quando a atualização feita pelo thread T1 na variável estática, isso se refletiu no T2.
fonte
Se declararmos uma variável como estática, haverá apenas uma cópia da variável. Portanto, sempre que diferentes threads acessarem essa variável, haverá apenas um valor final para a variável (pois há apenas um local de memória alocado para a variável).
Se uma variável for declarada como volátil, todos os threads terão sua própria cópia da variável, mas o valor será retirado da memória principal. Portanto, o valor da variável em todos os threads será o mesmo.
Portanto, nos dois casos, o ponto principal é que o valor da variável é o mesmo em todos os segmentos.
fonte