JAVA多线程系列--指令重排和happens-before规则
来源:互联网 发布:黑马程序员就业班 编辑:程序博客网 时间:2024/05/29 10:35
1 背景
我们在平时所习惯的单线程编程中默认了一种乐观的模型——串行一致性。即在程序中只存在唯一的操作执行顺序,并且在每次读取变量时,都能获得在执行序列(任何处理器)最近一次写入该变量的值。但在JVM底层的很多操作在现代多处理器架构中都不会提供这种串行一致性。这样是导致线程不完全问题的深层次原因。
导致非串行执行的原因是指令重排引起的,下面笔者将介绍下指令重排和规避指令重排的方法happens-before规则。
2 指令重排
2.1 指令重排是什么
Java 语言规范规定了JVM线程内部维持顺序化语义,也就是说只要程序的最终结果等同于它在严格的顺序化环境下的结果,那么指令的执行顺序就可能与代码的顺序不一致。这个过程通过叫做指令的重排序。指令重排序存在的意义在于:JVM能够根据处理器的特性(CPU的多级缓存系统、多核处理器等)适当的重新排序机器指令,使机器指令更符合CPU的执行特点,最大限度的发挥机器的性能。
2.2 重排序的背景
我们知道现代CPU的主频越来越高,与cache的交互次数也越来越多。当CPU的计算速度远远超过访问cache时,会产生cache wait,过多的cache wait就会造成性能瓶颈。
针对这种情况,多数架构(包括X86)采用了一种将cache分片的解决方案,即将一块cache划分成互不关联地多个 slots (逻辑存储单元,又名 Memory Bank 或 Cache Bank),CPU可以自行选择在多个 idle bank 中进行存取。这种 SMP 的设计,显著提高了CPU的并行处理能力,也回避了cache访问瓶颈。
2.3 重排序的种类
- 编译期重排
编译源代码时,编译器依据对上下文的分析,对指令进行重排序,以之更适合于CPU的并行执行。 - 运行期重排
CPU在执行过程中,动态分析依赖部件的效能,对指令做重排序优化。
3 happens-before规则
Java存储模型有一个happens-before原则,就是如果动作B要看到动作A的执行结果(无论A/B是否在同一个线程里面执行),那么A/B就需要满足happens-before关系。
(1)同一个线程中的每个Action都happens-before于出现在其后的任何一个Action。(2)对一个监视器的解锁happens-before于每一个后续对同一个监视器的加锁。(3)对volatile字段的写入操作happens-before于每一个后续的同一个字段的读操作。(4)Thread.start()的调用会happens-before于启动线程里面的动作。(5)Thread中的所有动作都happens-before于其他线程检查到此线程结束或者Thread.join()中返回或者Thread.isAlive()==false。(6)一个线程A调用另一个另一个线程B的interrupt()都happens-before于线程A发现B被A中断(B抛出异常或者A检测到B的isInterrupted()或者interrupted())。(7)一个对象构造函数的结束happens-before与该对象的finalizer的开始(8)如果A动作happens-before于B动作,而B动作happens-before与C动作,那么A动作happens-before于C动作。
以上原则归结为一点:happens-before规则是用来判断一个动作对另一个动作是否可见的法则。
4 总结
在真实环境下,如果动作A和动作B的执行顺序是可以通过指令重排发送变化的,但是你需要保证A和B的可见性,此时用户变可以用满足happens-before原则的操作来规避指令重排。比如用Java多线程工具类,如volatile,lock等。
阅读全文
0 0
- JAVA多线程系列--指令重排和happens-before规则
- 指令重排、happens-before规则
- 指令重排与happens-before
- Java多线程系列-happens-before规则和as-if-serial语义
- 多线程 happens-before规则
- Java多线程--happens-before
- java多线程之happens-before
- Java并发----ConcurrentHashMap01--(Happens-Before规则)
- happens-before规则解析
- happens-before规则
- happens-before的规则
- Java重排序和happens-before原则
- ConcurrentHashMap01--(Happens-Before规则)
- happens-before规则和as-if-serial语义
- Java Happens-before法则
- java-多线程深入(三)happens-before介绍
- Java多线程:volatile变量、happens-before关系及内存一致性
- Java并发编程系列之五:happens-before原则
- Hadoop2.9.0安装与配置(一)Linux centos7系统的安装与配置
- 【记录】memcpy后报错:segmentation fault
- 深度增强学习入门笔记(一)
- github相关
- NDk环境变量的配置、AS中配置javah-jni、ndk-build
- JAVA多线程系列--指令重排和happens-before规则
- python爬虫scrapy之贷联盟黑名单爬取
- Service需要了解的理论知识
- 计算机安全面临的常见问题分析
- ReactNative开发中使用react-native-vector-icons
- iOS8之后, 保存图片到本地相册, 避免重复保存同一张
- 关于请求被挂起页面加载缓慢问题的追查(stalled 时间过长)
- python_subprocess
- POJ 1493 Machined Surfaces G++