【Java 并发编程】指令重排序规范 ( happens-before 先行发生原则 )

简介: 【Java 并发编程】指令重排序规范 ( happens-before 先行发生原则 )

文章目录

一、指令重排序规范

二、happens-before 先行发生原则





一、指令重排序规范


指令重排指的是 , 线程中如果两行代码 没有逻辑上的上下关系 , 可以对代码进行 重新排序 ;



JVM 指令重排遵循规范 :


① as-if-serial 规范 : 单个线程中, 指令的重排 , 不能影响程序的执行结果 ;


可以重排的情况 : 对于下面代码 , 两条指令顺序颠倒 , 执行结果相同 , 可以进行指令重排 ;

x = 0;
y = 1;


不可以进行重排的情况 : 对于下面的代码 , 两条指令如果上下颠倒 , 结果不同 , 不可以进行指令重排 ;

x = 0;
y = x;



② happens-before 规范 : 先行发生原则 ;






二、happens-before 先行发生原则


happens-before 先行发生原则 : A happens-before B , A 先于 B 发生 , 先 A 后 B ;


Java 虚拟机在编译时和运行时 , 会对 JVM 指令进行重排优化 , 很明显 , 指令重排会对线程并发产生影响 ;


为了保证并发编程的安全性 , 这里 规定了一些场景下 , 禁止在这些场景中 使用 指令重排 ;



happens-before 先行发生原则 适用场景 : 在以下场景中 , 不进行指令重排 , 这些先后顺序 , 绝对不能被打乱 , 否则会出现严重线程安全问题 ;


程序次序原则 : 在程序内 , 按照代码书写的执行顺序 , 前面的代码先执行 , 后面的代码后执行 ; 时间上 靠前 的操作 先于 时间上靠后 的操作 执行 ;

管程锁规则 : 不论是单线程还是多线程 , 线程 A 解锁后 , 线程 B 获取该锁 , 可以看到线程 A 的操作结果 ; 解锁的操作 先于 加锁的操作 ; 线程 B 要加锁 , 必须等待线程 A 解锁完毕才可以 ;

volatile 规则 : volatile 关键字修饰的变量 , 线程 A 对该变量的写操作 先于 线程 B 读取该变量的操作 , 线程 A 对该变量的写操作的结果对于线程 B 一定可见 ;

线程启动规则 : 线程 start() 方法 先于 线程的具体执行的操作 ; 线程必须先启动 , 然后才能执行线程内的代码逻辑 ;

线程终止规则 : 线程的具体操作 先于 线程的终止检测 ; 线程的代码逻辑执行完成 , 然后进行线程的终止检测 ;

传递性 : happens-before 规则具有传递性 ; 如果 A happens-before B 和 B happens-before C , 则 A happens-before C ;

线程中断 : 调用线程 interrupt() 方法 , 先于 被中断线程的代码 检测到 中断时 事件的发生 ; 必须先发生中断 , 然后才能被检测到 ; 不能还没发生中断 , 就可以检测到中断发生 ;

对象终结 : 对象的创建 先于 对象的终结 , 创建就是调用构造函数 , 终结就是调用 finalize 方法 ;


只要符合上述规则 , 不需要进行同步 , 就可以成立 ;


通过 " happens-before 先行发生原则 " 可以判定两个线程的操作 , 是否有发生冲突的可能 ;


目录
相关文章
|
2月前
|
安全 IDE Java
Java常见规范及易忘点
遵循Java编程规范和注意易忘点是提高代码质量和可维护性的关键。通过规范的命名、格式、注释和合理的代码组织,可以让代码更加清晰和易于维护。同时,注意空指针检查、线程安全、集合框架和字符串操作等常见易忘点,可以减少程序错误,提高运行效率。结合单一职责原则、面向接口编程和合理的异常处理,能够编写出高质量的Java代码。希望本文能够帮助Java开发者提升编码水平,写出更高效、更可靠的代码。
33 2
|
3月前
|
存储 SQL 小程序
JVM知识体系学习五:Java Runtime Data Area and JVM Instruction (java运行时数据区域和java指令(大约200多条,这里就将一些简单的指令和学习))
这篇文章详细介绍了Java虚拟机(JVM)的运行时数据区域和JVM指令集,包括程序计数器、虚拟机栈、本地方法栈、直接内存、方法区和堆,以及栈帧的组成部分和执行流程。
52 2
JVM知识体系学习五:Java Runtime Data Area and JVM Instruction (java运行时数据区域和java指令(大约200多条,这里就将一些简单的指令和学习))
|
4月前
|
缓存 算法 Java
【Java引用规范】强软引用
本文详细介绍了Java中引用的概念和作用,包括强引用、软引用、弱引用和虚引用,并探讨了不同引用类型在内存管理和垃圾回收中的特性与用途。强引用是最常见的引用类型,对象只要被引用就不会被垃圾回收;软引用适用于内存敏感的缓存场景,在内存不足时会被回收;弱引用在更早的垃圾回收阶段被清除;虚引用主要用于对象的finalize过程。文章通过示例代码和内存分析工具展示了软引用的具体应用和回收机制。
【Java引用规范】强软引用
|
3月前
|
缓存 Java 数据库
JAVA分布式CAP原则
JAVA分布式CAP原则
83 0
|
3月前
|
Java 编译器 Android开发
java作业的提交规范与要求
java作业的提交规范与要求
36 0
|
3月前
|
缓存 前端开发 Java
Java中的RESTful API原则
总结而言,遵循RESTful原则不仅能够提升API的互操作性,还便于维护和扩展,是构建现代Web服务的重要实践。通过精心设计的URI、利用HTTP协议特性以及采用成熟框架如Spring Boot,Java开发者能够高效地创建出既强大又易于使用的RESTful API。
63 0
|
4月前
|
Java API 开发者
Java 注释规范
Java中的注释规范包括单行注释(`//`)、多行注释(`/* ... */`)和文档注释(`/** ... */`)。单行注释适用于简短说明,多行注释用于较长描述,文档注释则专为自动生成API文档设计。注释应清晰明了、及时更新,避免冗余,并详细说明参数和返回值。遵循这些规范有助于提高代码的可读性和可维护性。
249 5
|
5月前
|
Java 开发者
Java 编程风格与规范:跟上时代热点,打造高质量代码,为开发者梦想保驾护航
【8月更文挑战第30天】本文强调了Java编程中代码质量和可维护性的重要性,详细介绍了命名规范、代码格式和注释的最佳实践,如使用描述性的命名、适当的缩进及空行,以及关键代码部分的注释说明,同时还提供了避免魔法值和减少代码重复的建议与示例,帮助提升团队协作效率和项目长期发展。
86 2
|
5月前
|
Java
编写规范JAVA代码
本文档制定了Java编程规范,旨在确保系统源程序的可读性和可维护性,适用于所有Java开发、测试及维护过程。规范包括命名规则(如Package、Class及其成员等)与样式规定,强调统一风格以提高协作效率,并列举了具体示例与注意事项,如避免单字符变量名及使用有意义的反义词组命名等。
81 1
|
5月前
|
缓存 前端开发 Java
浅析JVM invokedynamic指令与Java Lambda语法
【8月更文挑战第27天】在Java的演进历程中,invokedynamic指令的引入和Lambda表达式的出现无疑是两大重要里程碑。它们不仅深刻改变了Java的开发模式和性能表现,还极大地推动了Java在函数式编程和动态语言支持方面的进步。本文将从技术角度浅析JVM中的invokedynamic指令及其与Java Lambda语法的紧密联系。
74 0