关于Java 并发常见面试题总结(中)“如何保证变量的可见性?”问题的答案详解
Ninguém assumiu esta issue ainda.
Avaliação
- Dificuldade
- 3/5
- Tempo estimado
- 1-2 dias
- Facilidade para iniciantes
- 35/100
- Tipo de issue
- Documentação
- Clareza
- Razoavelmente clara
- Status de atividade
- Estagnada
- Stack de tecnologia
- java
- Domínio
- documentation
Direção de pesquisa
Comece pela resposta de entrevista sobre concorrência em Java intitulada “如何保证变量的可见性?” e revise a explicação proposta e as fontes citadas neste issue. Verifique a redação sobre volatile, coerência de cache e memória principal e considere o trabalho concluído quando a resposta for corrigida e o PR enviado ou a decisão do maintainer for resolvido.
Escrita pelo modelo de indexação a partir do texto da issue.
Descrição
Guide哥你好,问题见下图,参考众多权威文献以及文章我认为,Java volatile关键字保证可见性是基于总线嗅探+缓存一致性协议(MESI协议),所以我认为并不是每次使用都会到主存中获取。
而MESI协议具体,我们可以从四个字母分别代表4种状态来理解:
- Modify(修改):当缓存行中的数据被修改时,该缓存行置为M状态
- Exclusive(独占):当只有一个缓存行使用某个数据时,置为E状态
- Shared(共享):当其他CPU中也读取某数据到缓存行时,所有持有该数据的缓存行置为S状态
- Invalid(无效):当某个缓存行数据修改时,其他持有该数据的缓存行置为I状态

以下图为例,我认为Java volatile变量保证可见性的原因,可以从这样一个场景理解(假设线程1在CPU1上,线程2在CPU上)
CPU1读取数据a=1,CPU1的缓存中都有数据a的副本,该缓存行置为(E)独占状态
CPU2也执行读取操作,同样CPU2也有数据a=1的副本,此时总线嗅探到CPU1也有该数据,则CPU1、CPU2两个缓存行都置为(S)共享状态
CPU1修改数据a=2,CPU1的缓存以及主内存a=2,同时CPU1的缓存行置为(S)状态,总线发出通知,CPU2收到通知将缓存行置为(I)无效状态
CPU2再次读取a,虽然CPU2在缓存中命中数据a=1,但是发现状态为(I),因此直接丢弃该数据,去主内存获取最新数据

所以我认为应该改为(答案已提交PR,劳烦Guide哥看看是否得当):
在 Java 中,volatile 关键字底层是基于总线嗅探机制和MESI缓存一致性协议保证变量的可见性,如果我们将变量声明为 volatile ,这就指示CPU,这个变量是共享且不稳定的,每次使用它时,处理器都会判断这个变量在缓存行中的状态是否因为其他处理器的修改变成无效(Invalid),若无效则重新从系统内存中把数据读取到处理器缓存。
参考文章:
- https://zhuanlan.zhihu.com/p/250657181
- Java书籍《Java并发编程的艺术》

- Linguagem predominante
- JavaScript
- Estrelas
- 159k
- Forks
- 46.1k
- Merge médio
- 3d 23h
- PRs com merge (30d)
- 6
Preparar o ambiente
Este projeto não oferece contêiner de desenvolvimento, Dockerfile nem guia de contribuição, então a configuração fica por sua conta: comece pelo README e veja nosso guia da primeira contribuição para os passos gerais.
Primeiros passos
- Leia a issue inteira e depois o guia de contribuição do projeto.
- Comente na issue dizendo que vai assumir — evita que duas pessoas façam o mesmo trabalho.
- Faça um fork do repositório e trabalhe em uma branch.
- Abra um pull request que referencie o número da issue.
Mais de Snailclimb/JavaGuide
-
[Issue] Maven 的中央仓库构件查询网址会自动跳转到另外一个网站Talvez já em andamento @jcbl1 assumiu há 3 dias. Aberta
Dificuldade 1/5 Menos de uma hora Facilidade para iniciantes 65/100
Snailclimb/JavaGuide#2927 ·
-
rocketmq 负载均衡策略对比 ,配图和表述不准Aberta
Dificuldade 2/5 1-3 horas Facilidade para iniciantes 45/100
Snailclimb/JavaGuide#2930 ·
-
masterAberta
Snailclimb/JavaGuide#2929 ·
-
Dificuldade 1/5 Menos de uma hora Facilidade para iniciantes 45/100
Snailclimb/JavaGuide#2649 · 2 comentários ·
-
perfect content
Dificuldade 1/5 Menos de uma hora Facilidade para iniciantes 55/100
Snailclimb/JavaGuide#2453 · 3 comentários ·
Todas as issues de Snailclimb/JavaGuide
Issues semelhantes
-
[dsh-plugin.org | dsh-plugin-hub] plugin distribution incomplete: yjh051108/dsh-routing-suiteAberta
Dificuldade 2/5 1-3 horas Facilidade para iniciantes 71/100
yjh051108/dsh-routing-suite#227 ·
-
needs-triage release-watch
Dificuldade 1/5 Menos de uma hora Facilidade para iniciantes 76/100
-
Dificuldade 2/5 1-3 horas Facilidade para iniciantes 68/100
dusk-network/exu#17 ·
-
Dificuldade 1/5 Menos de uma hora Facilidade para iniciantes 88/100
jspreadsheet/ce#1809 ·
-
documentation
Dificuldade 1/5 Menos de uma hora Facilidade para iniciantes 91/100
githubnext/gh-aw-workshop#4458 ·
Mantenedores costumam responder em até 1 dia