JMM内存模型总结

1、JMM是什么?

JMM是Java虚拟机规范中所定义的一种内存模型,它主要是用来定义程序中变量的访问规则。

在运行环境中,所有共享变量都存储在主存中,每个线程都有自己的工作内存(一个高速缓存,CPU的缓存存储层),工作内存中保存的是主存中变量的副本,而线程对于共享变量的读写操作都是在工作内存中进行的,而不是直接读写主存中的变量。所以在多线程操作的环境下,就会有线程安全的问题。(划分了工作内存和主存)

2、JMM如何控制Java线程之间的通信?

JMM决定了一个线程对于共享变量的写入什么时候对另一个线程可见。

例如,线程A与线程B进行通信:将线程A中的“x = 1”传递给线程B。

首先,将线程A中工作内存存储的共享变量副本“x = 1”刷新到主存中。

然后,线程B去主存中读取线程A更新过的共享变量。得到线程A传递来的“x = 1”。

3、重排序是什么?

在执行程序的时候为了提高性能,编译器和处理器会对指令进行重排序:

(1)编译器优化的重排序:在不改变单线程程序语义的前提下,重新安排语句的执行顺序。

(2)指令级并行的重排序:如果不存在数据依赖性,那么可以让多条指令重叠执行。

(3)内存系统的重排序:由于处理器使用缓存和读/写缓冲区,会使加载和存储操作看上去可能是乱序执行。

4、JMM如何处理重排序?

对于编译器:JMM会禁止特定类型的编译器重排序。

对于处理器:JMM会要求Java编译器在生成指令序列的时候,插入特定类型的内存屏障指令,通过内存屏障指令来禁止特定类型的处理器重排序。(Load是读取指令,Store是写入指令)

(1)LoadLoad 屏障: 对于这样的语句 Load1; LoadLoad; Load2,在 Load2 及后续读取操作要读取的数据被访问前,保证 Load1 要读取的数据被读取完毕。

(2)StoreStore 屏障: 对于这样的语句 Store1; StoreStore; Store2,在 Store2 及后续写入操作执行前,保证Store1 的写入操作对其它处理器可见。

(3)LoadStore 屏障: 对于这样的语句 Load1; LoadStore; Store2,在 Store2 及后续写入操作被执行前,保证Load1 要读取的数据被读取完毕。

(4)StoreLoad 屏障: 对于这样的语句 Store1; StoreLoad; Load2,在 Load2 及后续所有读取操作执行前,保证Store1 的写入对所有处理器可见。

StoreLoad 它的开销是四种屏障中最大的(冲刷写缓冲器,清空无效化队列)。在大多数处理器的实现中,这个屏障也被称为全能屏障,兼具其它三种内存屏障的功能。

5、happens-before是什么?

从JDK5之后,Java开始使用JSR-133内存模型。JSR-133内存模型提出了happens-before概念,happens-before阐述了操作之间的内存可见性。如果一个操作的结果需要对另一个操作可见,那么这两个操作之间必须存在happens-before关系。((1)仅代表A操作对B操作可见,(2)但不代表A操作必须先于B操作执行)

上面的1)是JMM对程序员的承诺。从程序员的角度来说,可以这样理解happens-before关系:如果A happens-before B,那么Java内存模型将向程序员保证——A操作的结果将对B可见,且A的执行顺序排在B之前。注意,这只是Java内存模型向程序员做出的保证!

上面的2)是JMM对编译器和处理器重排序的约束原则。正如前面所言,JMM其实是在遵循一个基本原则:只要不改变程序的执行结果(指的是单线程程序和正确同步的多线程程序),编译器和处理器怎么优化都行。JMM这么做的原因是:程序员对于这两个操作是否真的被重排序并不关心,程序员关心的是程序执行时的语义不能被改变(即执行结果不能被改变)。

从上图可以看出两点:

  • JMM 向程序员提供的 happens- before 规则能满足程序员的需求。JMM 的 happens- before 规则不但简单易懂,而且也向程序员提供了足够强的内存可见性保证(有些内存可见性保证其实并不一定真实存在,比如上面的 A happens- before B)。
  • JMM 对编译器和处理器的束缚已经尽可能的少。从上面的分析我们可以看出,JMM 其实是在遵循一个基本原则:只要不改变程序的执行结果(指的是单线程程序和正确同步的多线程程序),编译器和处理器怎么优化都行。比如,如果编译器经过细致的分析后,认定一个锁只会被单个线程访问,那么这个锁可以被消除。再比如,如果编译器经过细致的分析后,认定一个 volatile 变量仅仅只会被单个线程访问,那么编译器可以把这个 volatile 变量当作一个普通变量来对待。这些优化既不会改变程序的执行结果,又能提高程序的执行效率。

Java 内存模型就是通过以上定义的这些来解决可见性、原子性和有序性问题的。

参考资料:

JVM 基础 - Java 内存模型详解 | Java 全栈知识体系

从 PC 内存架构到 Java 内存模型 | JavaKeeper

JMM内存模型_MrHamster的博客-CSDN博客_jmm内存模型

详解JMM - 简书

happens-before 规则_Mattie梓轩的博客-CSDN博客_happens-before

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值