什么是JAVA内存模型
JMM是一种规范,目的是解决由于多线程通过共享内存进行通信时,存在的本地内存数据不一致、编译器会对代码指令重排序、处理器会对代码乱序执行等带来的问题。
Java内存模型规定了所有的变量都存储在主内存中,每条线程还有自己的工作内存,线程的工作内存中保存了该线程中是用到的变量的主内存副本拷贝,线程对变量的所有操作都必须在工作内存中进行,而不能直接读写主内存。不同的线程之间也无法直接访问对方工作内存中的变量,线程间变量的传递均需要自己的工作内存和主存之间进行数据同步进行。
而JMM就作用于工作内存和主存之间数据同步过程。他规定了如何做数据同步以及什么时候做数据同步。
为什么需要JAVA内存模型
缓存不一致:每个cpu都有单独寄存器,多线程的情况下会导致不同的cpu的寄存器中的缓存不一致
重排序
Processor A | Processor B |
a = 1; //A1 | b = 2; //B1 |
初始状态:a = b = 0 可能的结果:x=y=0 |
编译器重排序
编译器在不改变单线程程序语义的前提下,可以重新安排语句的执行顺序,在不改变程序语义的前提下,尽可能减少寄存器的读取、存储次数,充分复用寄存器的存储值。
- 指令1计算一个值赋给变量A并存放在寄存器中
- 指令2与A无关但需要占用寄存器
- 指令3执行时A重新被读入寄存器
1 > 2 > 3 会优化成 1 > 3 > 2
指令重排序
指令集并行的重排序是对CPU的性能优化,从指令的执行角度来说一条指令可以分为多个步骤完成,如下:
- 取指 IF
- 译码和取寄存器操作数 ID
- 执行或者有效地址计算 EX
- 存储器访问 MEM
- 写回 WB
多条指令可以同时存在于流水线中,同时被执行。指令流水线并不是串行的,并不会因为一个耗时很长的指令在“执行”阶段呆很长时间,而导致后续的指令都卡在“执行”之前的阶段上。相反,流水线是并行的,多个指令可以同时处于同一个阶段,只要CPU内部相应的处理部件未被占满即可。
内存重排序