-
happens-before与JMM的关系
-
需要关注的问题
JMM是语言级的内存模型,在我的理解中JMM处于中间层,包含了两个方面:(1)内存模型;(2)重排序以及happens-before规则。同时,为了禁止特定类型的重排序会对编译器和处理器指令序列加以控制。而上层会有基于JMM的关键字和J.U.C包下的一些具体类用来方便程序员能够迅速高效率的进行并发编程。站在JMM设计者的角度,在设计JMM时需要考虑两个关键因素:
- 程序员对内存模型的使用
程序员希望内存模型易于理解、易于编程。程序员希望基于一个强内存模型来编写代码。
- 编译器和处理器对内存模型的实现
编译器和处理器希望内存模型对它们的束缚越少越好,这样它们就可以做尽可能多的优化来提高性能。编译器和处理器希望实现一个弱内存模型。
另外还要一个特别有意思的事情就是关于重排序问题,更简单的说,重排序可以分为两类:
-
会改变程序执行结果的重排序。
-
不会改变程序执行结果的重排序。
JMM对这两种不同性质的重排序,采取了不同的策略,如下。
-
对于会改变程序执行结果的重排序,JMM要求编译器和处理器必须禁止这种重排序。
-
对于不会改变程序执行结果的重排序,JMM对编译器和处理器不做要求(JMM允许这种
重排序)
JMM的设计图为:
从图可以看出:
-
JMM向程序员提供的happens-before规则能满足程序员的需求。JMM的happens-before规则不但简单易懂,而且也向程序员提供了足够强的内存可见性保证(有些内存可见性保证其实并不一定真实存在)。
-
JMM对编译器和处理器的束缚已经尽可能少。从上面的分析可以看出,JMM其实是在遵循一个基本原则:只要不改变程序的执行结果(指的是单线程程序和正确同步的多线程程序),编译器和处理器怎么优化都行。例如,如果编译器经过细致的分析后,认定一个锁只会被单个线程访问,那么这个锁可以被消除。再如,如果编译器经过细致的分析后,认定一个volatile变量只会被单个线程访问,那么编译器可以把这个volatile变量当作一个普通变量来对待。这些优化既不会改变程序的执行结果,又能提高程序的执行效率。
![happens-before与JMM的关系](https://imgconvert.csdnimg.cn/aHR0cHM6Ly9yYXcuZ2l0aHVidXNlcmNvbnRlbnQuY29tL0pvdXJXb24vaW1hZ2UvbWFzdGVyL0phdmElRTUlQjklQjYlRTUlOEYlOTElRTclQkMlOTYlRTclQTglOEItJUU1JUI5JUI2JUU1JThGJTkxJUU3JTkwJTg2JUU4JUFFJUJBL2hhcHBlbnMtYmVmb3JlJUU0JUI4JThFSk1NJUU3JTlBJTg0JUU1JTg1JUIz
《一线大厂Java面试题解析+后端开发学习笔记+最新架构讲解视频+实战项目源码讲义》
【docs.qq.com/doc/DSmxTbFJ1cmN1R2dB】 完整内容开源分享
JUU3JUIzJUJCLnBuZw?x-oss-process=image/format,png)