JMM
JMM
JVM规范中视图定义一种Java内存模型(java Memory Model)JMM,来屏蔽掉各种硬件和操作系统的内存访问差异
,实现Java程序在各种平台下都能达到一致的内存访问效果。
原则
JMM的关键技术点事围绕多线程的原子性、可见性、有序性展开的
JMM三大特性
- 可见性
指当一个线程修改了某个变量的值,其他线程是否能够立即知道该变更,JMM规定了所有的变量都存储在主内存中
不同线程间无法直接访问对方工作内存中的变量,线程间变量值的传递均需要通过主内存来完成。
共享变量变更过程
线程读取 主内存的共享变量到工作内存,修改工作内存的值后,再提交给主内存实现变更。
优点:提升CPU效率,串行语义一致
缺点:不保证多线程间的语义一致(可能产生“脏读”)。
- 原子性
- 指令重排序
为了提升性能,编译器和处理器通常会对指令序列进行重新排序。Java规范规定JVM线程内部维持顺序化语义,只要程序的最终结果与它顺序化执行的结果相等,那么指令的顺序可以与代码顺序不一致。
源代码=> 编译器优化的重排=>指令并行的重排=>内存系统的重排=>最终执行的指令
处理器在进行重排序时,必须考虑指令之间的数据依赖性
- 有序性
happens-before:先行发生 原则
在JMM中,如果一个执行的结果需要对另一个操作可见性,或者 代码重排序,那么这两个操作之间必须存在happens-before(先行发生)原则。逻辑上的先后关系
happens-beforen保证可见性和有序性的约束
总原则:
- 如果一个操作happens-before另一个操作,那么第一个操作的执行结果将对第二个操作可见,而且第一个操作的执行顺序排在第二个操作之前。
- 两个操作之间存在happens-before关系,并不意味着一定按照happens-before原则制定的顺序来执行,如果重排序之后的执行结果与happens-before关系执行的结果 一致,那么这种重排序并不非法。
happens-before之8条
- 次序规则
一个线程内,按照代码的顺序写在前面的操作先行发生于写在后面的额操作。前一个操作的结果可以被后续的操作获取。
- 锁定规则
一个unLock操作先行发生于后面(时间上的先后),对同一个锁的lock操作
- volatile变量规则
对于一个volatile变量的写操作先行发生于后面对这个变量的读操作,前面的写对后面(时间上的后面)的读是可见的
- 传递规则
如果操作A先行发生于操作B,操作B先行发生于操作C,则可以得出操作A先行发生于操作C
- 线程启动规则
Thread对象的start()方法先行发生于此线程的每一个动作
- 线程中断规则
- 对线程interrupt()方法的调用发生于被中断线程的代码检测到中断事件的发生
- 可以通过Thread.interrupt()检测到是否发生中断。
- 先调用interrupt()方法设置过中断标志位,才能检测到中断发送
- 线程终止规则
线程中的所有操作都先行发生于对此线程的终止检测,可以通过isAlive()等手段检测线程是否已经终止
- 对象终结规则
一个对象的初始化完成(构造函数执行结束)先行发生于它的finalize()方法的开始
对象没有完成初始化之前,不能调用finalize()方法的
- 本文标签: Java
- 本文链接: http://119.91.109.247:8443//article/82
- 版权声明: 本文由张亚东原创发布,转载请遵循《署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0)》许可协议授权