java memory model(java内存模型)


简介

在并发编程中, 我们需要处理两个关键问题:

  • 线程之间如何通信。通信是指线程之间交换信息。(由JMM控制)
  • 线程之间如何同步。同步是指程序操作发生的相对顺序。(由并发工具支持, synchronized同步锁、CyclicBarrier等)

在命令式编程中, 线程之间的通信机制有两种:

  • 共享内存(Java)
  • 消息传递(Go)

重排序

Java源代码到最终实际执行的指令序列, 会经理下面三种重排序:

  1. 源代码 -> 编译器优化重排序
  2. -> 指令级并行重排序
  3. -> 内存系统重排序 -> 最终执行的指令序列

禁止编译器重排序: JMM的编译器重排序规则会禁止特定类型的编译器重排序
禁止处理器重排序: JMM通过插入内存屏障

happens-before

JMM属于语言级的内存模型, 它确保在不同的编译器和处理器上 为程序员员提供一致的内存可见性(通过禁止特定类型的编译器重排序和处理器重排序)。

  • 程序顺序规则: 一个线程中的每个操作, happens-before于该线程中的任意操作
  • 监视器锁规则: 对一个监视器的解锁, happens-before于随后对这个监视器的加锁

cpu写缓冲区

现代的cpu使用写缓冲区来临时保存向内存写入的数据。

写缓冲区的优点

  1. cpu不必停顿下来等待向内存写入数据, 这种停顿等待会打断流水线的持续运行。
  2. 通过以批处理的方式刷新写缓冲区, 以及合并写缓冲区对同一内存地址的多次写, 减少对内存总线的占用

写缓冲区带来的问题

处理器对内存的读/写操作的执行顺序, 不一定与内存实际发生的读/写操作顺序一致

缓存一致性协议

常见的缓存一致性协议有:MESI,MESIF(MESIF是缓存行的状态标识,M:Modified, E: Exclusive, S:Shared, I:Invalid, F: Forwad),通过标记缓存行的状态和处理器间的通讯来实现。

volatile

参考文章

  1. happens-before
  2. 指令重排、内存屏障概念解析
  3. Intel文档
  4. cmpxchg指令
  5. x86寄存器
  6. ZF标志
  7. The JSR-133 Cookbook for Compiler Writers
  8. Java并发编程常识
  9. [资料合集] RednaxelaFX写的文章/回答的导航帖(work in progress)
  10. 讲真,我发现这本书有个地方写错了! 溢出 or 逸出?
  11. 聊聊JMM
  12. 面试官告诉你什么是JMM和常考面试题

文章作者: 金龙
版权声明: 本博客所有文章除特別声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 金龙 !
  目录