JMM

756 字
4 分钟
JMM

CPU多级缓存结构与CPU缓存一致性协议MESI#

image 31
image 31

硬件层面:

  • 多核处理器缓存架构导致多个处理器之间的缓存一致性问题
  • 为了解决缓存一致性问题引入了缓存一致性协议MESI

软件层面:

  • 硬件层面上,处理器其实并不知道何时需要使用内存屏障指令,它只是提供内存屏障的能力,然后将决定权交给软件层
  • 软件层面上JVM 抽象处理 Java 内存模型 JMM 来定义线程本地内存和主内存之间的关系,并提供 volatile 关键字来让软件层面调用底层的内存屏障来解决多线程之间的可见性问题
  • Java 规范中有 as-if-serial 和 happens-before 原则 as-if-serial

**不管怎么重排序(编译器和处理器为了提高并行度),(单线程)程序的执行结果不能被改变。**编译器、runtime 和处理器都必须遵守 as-if-serial 语义。 为了遵守 as-if-serial 语义,编译器和处理器不会对存在数据依赖关系的操作做重排序,因为这种重排序会改变执行结果。但是,如果操作之间不存在数据依赖关系,这些操作就可能被编译器和处理器重排序。

happens-before

对于两个操作A和B,这两个操作可以在不同的线程中执行。如果A Happens-Before B,那么可以保证,当A操作执行完后,A操作的执行结果对B操作是可见的

  1. 程序顺序规则:在同一个线程中,书写在前面的操作happen-before后面的操作。
  2. volatile变量规则:对一个volatile域的写,happens-before于任意后续对此变量的操作。
  3. 监视器锁规则:对一个锁的解锁,happens-before于随后对这个锁的加锁。
  4. 传递性:如果A happens-before B,且B happens-before C,那么A happens-before C。
  5. start()规则:如果线程A执行操作ThreadB.start()(启动线程B),那么A线程的ThreadB.start()操作happens-before于线程B中的任意操作。
  6. join()规则:如果线程A执行操作ThreadB.join()并成功返回,那么线程B中的任意操作happens-before于线程A从ThreadB.join()操作成功返回。
  7. 程序中断规则:对线程interrupted()方法的调用happens-before于被中断线程的代码检测到中断时间的发生。
  8. 对象finalize规则:一个对象的初始化完成(构造函数执行结束)happens-before于它的finalize()方法的开始。

JMM#

原子性

JMM 通过关键字 synchronized 实现原子性。底层通过 monitorenter/monitorexit 指令来实现

可见性

共享变量的修改对其他线程可见。JMM 通过 volatile 关键字保证对共享变量的修改可以马上刷新到主内存,且其他线程操作共享变量必须从主内存获取最新值。

有序性

禁止重排序,确保可见性,底层是内存屏障。

📎 参考文章#

文章分享

如果这篇文章对你有帮助,欢迎分享给更多人!

JMM
https://blog.sephy.top/posts/jmm/
作者
虾米
发布于
2023-08-15
许可协议
CC BY-NC-SA 4.0
Profile Image of the Author
虾米
coder
分类
标签
站点统计
文章
61
分类
4
标签
52
总字数
64,663
运行时长
0
最后活动
0 天前
站点信息
构建平台
GitHub Actions
博客版本
Firefly v6.13.9
文章许可
CC BY-NC-SA 4.0