手机手机网站制作,建设网站用户名,iis默认网站删除,it外包考核目录1. 如何解决重排序带来的问题2. happens-before1. 如何解决重排序带来的问题
对于编译器#xff0c;JMM 的编译器重排序规则会禁止特定类型的编译器重排序。对于处理器重排序#xff0c;JMM 的处理器重排序规则会要求编译器在生成指令序列时#xff0c;插入特定类型的内…
目录1. 如何解决重排序带来的问题2. happens-before1. 如何解决重排序带来的问题
对于编译器JMM 的编译器重排序规则会禁止特定类型的编译器重排序。对于处理器重排序JMM 的处理器重排序规则会要求编译器在生成指令序列时插入特定类型的内存屏障Memory Barries / Memory Fence指令通过内存屏障指令来禁止特定类型的处理器重排序。
由于常见的处理器内存模型比 JMM 要弱Java 编译器在生成字节码时会在执行指令序列的适当位置插入内存屏障来限制处理器的重排序。同时由于各种处理器内存模型的强弱不同为了在不同的处理器平台向程序员展示一个一致的内存模型JMM 在不同的处理器中需要插入的内存屏障的数量和种类也不同。
CPU内存屏障
LoadLoad禁止读和读的重排序StoreStore禁止写和写的重排序LoadStore禁止读和写的重排序StoreLoad禁止写和读的重排序。
Java内存屏障
public final class Unsafe { // LoadLoad LoadStore public native void loadFence();// StoreStore LoadStore public native void storeFence();// loadFence() storeFence() StoreLoad public native void fullFence();
}2. happens-before
JMM 使用 happens-before 规则来阐述操作之间的内存可见性以及什么时候不能重排序。
在 JMM 中 如果一个操作执行的结果需要对另一个操作可见那么这两个操作之间必须要存在 happens-before 关系。换个角度来说如果A happens-before B则意味着A的执行结果必须对B可见也就是保证跨线程的内存可见性。
其中4条规则与程序员密切相关。
程序顺序规则一个线程中的每个操作happens-before 于该线程中的任意后续操作volatile 变量规则对一个 volatile 域的写happens-before 于任意后续对这个 volatile 域的读synchronized 规则对一个锁的解锁happens-before 于随后对这个锁的加锁传递性若 A happens-before B且 B happens-before C则 A happens-before Cstart() 规则若线程 A 执行 ThreadB.start()则线程 A 的这个操作 happens-before 于线程 B 中的任意操作join() 规则若线程 A 执行 ThreadB.join() 并成功返回那么线程 B 中的任意操作 happens-before 于线程 A 从 ThreadB.join() 的成功返回。
举个栗子
假设线程 A 执行 writer() 方法之后线程 B 执行 reader() 方法。根据 happens-before 规则这个过程建立的 happens-before 关系可以分为 3 类
根据顺序规则1 happens-before 23 happens-before 4根据 volatile 规则2 happens-before 3根据 happens-before 的传递性规则1 happens-before 4。
public class Test2 {int a 0;volatile boolean flag false;public void writer() {// 1a 1;// 2flag true;}public void reader() {// 3if (flag) {// 4int i a;}}
}更多关于「happens-before 和 as-if-serial 语义」请详细看这篇文章-Java并发编程之happens-before和as-if-serial语义