[TOC]
Java内存模型规范(JSR-133)是围绕原子性、可见性和有序性展开的。
## 原子性、可见性、有序性
![](https://img.kancloud.cn/b8/aa/b8aa875f8d9cb647fcfbb7d67c927f5b_1472x652.png)
如下图说明了Java线程、工作内存和主存之前的关系。
![](https://img.kancloud.cn/d8/ce/d8ce0de964d06a7b79cdd903bb70b5d6_1278x860.png)
Java内存模型(JMM)定义了一套自己的主存到工作内存之间的交互协议,即一个变量如何从主存拷贝到工作内存,又如何从工作内存写入主存,该协议包含8种操作,并且要求JVM具体实现必须保证其中每一种操作都是原子的、不可再分的。
8种操作分别是:
![](https://img.kancloud.cn/ba/94/ba949c07584b4381c9814142dc8c1a4e_1174x570.png)
如下图描述了以上8个操作所在位置:
![](https://img.kancloud.cn/8a/e7/8ae7e83cd040c1240eaa14eb1dc39aae_1088x724.png)
## 什么是指令重排,为什么需要?
要搞懂指令重排,首先要知道一条指令在CPU内是如何执行的,如下图约5个步骤。
![](https://img.kancloud.cn/22/a2/22a2fb26c288e7b1c0dcf393b6d269ee_1478x380.png)
为了加快指令并行速度,CPU硬件支持了流水线技术。
![](https://img.kancloud.cn/e1/4b/e14baa9d4e47e34564da5c11ed450819_1472x518.png)
不同的指令步骤执行在不同的硬件局部,从而可以支持同时并发执行。
![](https://img.kancloud.cn/1e/b0/1eb023edfbc07ca797b53fd55cd54530_1344x1000.png)
知道了CPU流水线之后,我们来看一个A=B+C的流水线执行过程例子:
![](https://img.kancloud.cn/79/b1/79b136d144d4a8dddf48e555d9b671ec_1474x716.png)
如果按串行排列,则耗时4 * 5 = 20个时钟周期;使用CPU流水线并行技术后,可以只消耗9个时钟周期,节省了11个时钟周期的时间。所以流水线技术的引入,大大提高了CPU并行执行速度。
再看如下图的例子:
![](https://img.kancloud.cn/19/a3/19a300dea893de502710a8f75741b603_1466x1664.png)
多条语句执行时,通过指令重排(CPU指令级重排序)可以消除一些CPU中断,从而缩短执行时间,加快执行速度。
## 重排序
![](https://img.kancloud.cn/5e/cd/5ecd7cbd67907995e866859bda6cf9bd_1612x392.png)
对于Java语言来说,为了提高新能,从源码到得到指令执行序列可能会经过编译器重排序和CPU重排序;CPU重排序又分为指令级重排和内存系统重排。
### 编译器重排序
编译器重排序指的是在代码编译阶段进行指令重排,不改变程序执行结果的情况下,为了提升效率,编译器对指令进行乱序(Out-of-Order)的编译。
### CPU重排序
流水线(Pipeline)和乱序执行(Out-of-Order Execution)是现代CPU基本都具有的特性。
所谓“乱序”,仅仅是被称为“乱序”,实际上也遵循着一定规则:只要两个指令之间不存在“数据依赖”,就可以对这两个指令乱序。
CPU重排序包括两类:指令级重排序和内存系统重排序。
* 指令级重排序
在不影响程序执行结果的情况下,CPU内核采用ILP(Instruction-Level Parallelism,指令级并行运算)技术来将多条指令重叠执行,主要是为了提升效率。如果指令之间不存在数据依赖性,CPU就可以改变语句的对应机器指令的执行顺序,叫作指令级重排序。
* 内存系统重排序
对于现代的CPU来说,在CPU内核和主存之间都具备一个高速缓存,高速缓存的作用主要是减少CPU内核和主存的交互(CPU内核的处理速度要快得多),在CPU内核进行读操作时,如果缓存没有的话就从主存取,而对于写操作都是先写在缓存中,最后再一次性写入主存。
由于处理器使用缓存和读/写缓冲区,这使得加载和存储操作看上去可能是在乱序执行。
## 哪些指令不能重排:Happen-Before原则(先行发生)
![](https://img.kancloud.cn/f8/26/f8269f3faba8dee43fbf5a6302ac1588_1472x1036.png)
## 参考文档
* 书籍:葛一鸣 *《Java高并发程序设计第二版》
* 书籍:周志明 *《深入理解Java虚拟机》
- 面试突击
- Java虚拟机
- 认识字节码
- 000Java发展历史
- 000Macos10.15.7上编译OpenJDK8u
- 001熟悉Java内存区域
- 002熟悉HotSpot中的对象
- 003Java如何计算对象大小
- 004垃圾判定算法与4大引用
- 005回收堆和方法区中对象
- 006垃圾收集算法
- 007HotSpot虚拟机垃圾算法实现篇1
- 007HotSpot虚拟机垃圾算法实现篇2
- 007HotSpot虚拟机垃圾算法实现篇3
- 008垃圾收集器
- 009内存分配与回收策略
- 010Java虚拟机相关工具
- 011调优案例分析
- 012一次IDEA的启动速度调优
- 013类文件Class的结构
- 014熟悉字节码指令
- 015类加载机制(过程)
- 016类加载器
- IDEA的JVM参数
- Java基础
- Java自动装箱与拆箱
- Java基础数据类型
- Java方法的参数传递
- Java并发
- 001走入并行的世界
- 002并行程序基础
- 003熟悉Java内存模型JMM
- 004Java并发之volatile关键字
- 005线程池入门到精通
- 006Java多线程间的同步控制方法
- 007Java维基准测试框架JMH
- 008Java并发容器
- 009Java的线程实现
- 010Java关键字synchronized
- 011一些并行模式的熟悉
- 单例模式和不变模式
- 生产者消费者模式
- Future模式
- 012一些并行算法的熟悉
- 面试总结
- 长亮一面