关于Java 并发常见面试题总结(中)“如何保证变量的可见性?”问题的答案详解
Dieses Issue hat noch niemand übernommen.
Bewertung
- Schwierigkeit
- 3/5
- Geschätzter Aufwand
- 1-2 Tage
- Anfängerfreundlichkeit
- 35/100
- Issue-Typ
- Dokumentation
- Klarheit
- Größtenteils klar
- Aktivitätsstatus
- Veraltet
- Tech-Stack
- java
- Bereich
- documentation
Rechercherichtung
Beginnen Sie mit der Java-Concurrency-Interviewantwort mit dem Titel „如何保证变量的可见性?“ und prüfen Sie die in diesem Issue vorgeschlagene Erklärung und die zitierten Quellen. Überprüfen Sie die Aussagen zu volatile, Cache-Kohärenz und Hauptspeicher und betrachten Sie die Arbeit als abgeschlossen, sobald die Antwort korrigiert und der eingereichte PR oder die Entscheidung des Maintainers geklärt ist.
Vom Indexierungsmodell aus dem Issue-Text verfasst.
Beschreibung
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并发编程的艺术》

- Vorherrschende Sprache
- JavaScript
- Sterne
- 159k
- Forks
- 46.1k
- Ø Merge
- 1 T. 8 Std.
- Gemergte PRs (30 T.)
- 10
Beitragsleitfaden
Für dieses Repository ist kein Beitragsleitfaden indexiert
Erste Schritte
- Lesen Sie das ganze Issue und danach den Beitragsleitfaden des Projekts.
- Schreiben Sie ins Issue, dass Sie es übernehmen — das erspart doppelte Arbeit.
- Forken Sie das Repository und arbeiten Sie in einem Branch.
- Öffnen Sie einen Pull Request, der die Issue-Nummer nennt.
Mehr aus Snailclimb/JavaGuide
-
失效链接替换 Offen
Schwierigkeit 1/5 Unter einer Stunde Anfängerfreundlichkeit 78/100
Snailclimb/JavaGuide#2922 · 1 Kommentar ·
-
Schwierigkeit 1/5 Unter einer Stunde Anfängerfreundlichkeit 45/100
Snailclimb/JavaGuide#2649 · 2 Kommentare ·
-
perfect content
Schwierigkeit 1/5 Unter einer Stunde Anfängerfreundlichkeit 55/100
Snailclimb/JavaGuide#2453 · 3 Kommentare ·
-
关于Disruptor中填充了多少字节的补充 Offenperfect content
Schwierigkeit 3/5 1-2 Tage Anfängerfreundlichkeit 35/100
Snailclimb/JavaGuide#2259 · 2 Kommentare ·
-
Schwierigkeit 3/5 1-2 Tage Anfängerfreundlichkeit 35/100
Snailclimb/JavaGuide#2074 ·
Alle Issues in Snailclimb/JavaGuide
Ähnliche Issues
-
Update HugeIcons library Offen
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 65/100
antfu-collective/icones#398 ·
-
ECmail.com Offen
Schwierigkeit 1/5 Unter einer Stunde Anfängerfreundlichkeit 90/100
wesbos/burner-email-providers#554 ·
-
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 65/100
radiantearth/stac-browser#1023 ·
-
HMR stops working Offen
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 75/100
-
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 75/100
components-web-app/docs#92 ·