关于Java 并发常见面试题总结(中)“如何保证变量的可见性?”问题的答案详解
Nadie ha tomado este issue todavía.
Evaluación
- Dificultad
- 3/5
- Tiempo estimado
- 1-2 días
- Aptitud para principiantes
- 35/100
- Tipo de issue
- Documentación
- Claridad
- Bastante claro
- Estado de actividad
- Estancado
- Stack tecnológico
- java
- Área
- documentation
Línea de trabajo
Comienza con la respuesta de la entrevista sobre concurrencia de Java titulada “如何保证变量的可见性?” y revisa la explicación propuesta y las fuentes citadas en este issue. Verifica lo dicho sobre volatile, la coherencia de caché y la memoria principal, y considera el trabajo completo cuando la respuesta esté corregida y se haya resuelto el PR enviado o la decisión del maintainer.
Escrito por el modelo de indexación a partir del texto del issue.
Descripción
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并发编程的艺术》

- Lenguaje dominante
- JavaScript
- Estrellas
- 159k
- Forks
- 46.1k
- Merge medio
- 1 d 8 h
- PR fusionados (30 d)
- 10
Guía de contribución
No hay ninguna guía de contribución indexada para este repositorio
Primeros pasos
- Lee el issue completo y luego la guía de contribución del proyecto.
- Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
- Haz un fork del repositorio y trabaja en una rama.
- Abre un pull request que haga referencia al número del issue.
Más de Snailclimb/JavaGuide
-
失效链接替换 Abierto
Dificultad 1/5 Menos de una hora Aptitud para principiantes 78/100
Snailclimb/JavaGuide#2922 · 1 comentario ·
-
关于数组转集合方法的第六种:使用Java9的List.of() Abierto
Dificultad 1/5 Menos de una hora Aptitud para principiantes 45/100
Snailclimb/JavaGuide#2649 · 2 comentarios ·
-
perfect content
Dificultad 1/5 Menos de una hora Aptitud para principiantes 55/100
Snailclimb/JavaGuide#2453 · 3 comentarios ·
-
关于Disruptor中填充了多少字节的补充 Abiertoperfect content
Dificultad 3/5 1-2 días Aptitud para principiantes 35/100
Snailclimb/JavaGuide#2259 · 2 comentarios ·
-
Dificultad 3/5 1-2 días Aptitud para principiantes 35/100
Snailclimb/JavaGuide#2074 ·
Todos los issues de Snailclimb/JavaGuide
Issues similares
-
awaiting triage bug Causes friction Hop Gui P1 P2 Transforms
Dificultad 2/5 1-3 horas Aptitud para principiantes 75/100
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 75/100
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 75/100
-
Improve Title Support Abierto
Dificultad 2/5 1-3 horas Aptitud para principiantes 70/100
georgestephanis/p2026#40 ·
-
Enatega Customer and Rider app: Add-ons price is not visible to customer after order is placed. Abierto
Dificultad 2/5 1-3 horas Aptitud para principiantes 75/100
Margaret-Petersen/food-delivery-app-clone-react-native#1981 ·