happens-before原则,一定程度上避免指令重排
编译器、指令器可能对代码重排序、乱排、要守一定的规则,happens-before原则。只要符合happens-before的原则,那么就不能胡乱重排序,如果不符合这个规则,那么就可以自己排序。
happens-before八大原则
- 单线程happen-before原则:在同一个线程中,书写在前面的操作happen-before后面的操作。
- 锁的happen-before原则:同一个锁的unlock操作happen-before此锁的lock操作。
- volatile的happen-before原则:对一个volatile变量的写操作happen-before对此变量的任意操作(当然也包括写操作了)。
- happen-before的传递性原则:如果A操作 happen-before B操作,B操作happen-before C操作,那么A操作happen-before C操作。
- 线程启动的happen-before原则:同一个线程的start方法happen-before此线程的其它方法。
- 线程中断的happen-before原则:对线程interrupt方法的调用happen-before被中断线程的检测到中断发送的代码。
- 线程终结的happen-before原则:线程中的所有操作都happen-before线程的终止检测。
- 对象创建的happen-before原则:一个对象的初始化完成先于他的finalize方法调用。
有过有面试官问happens-before原则,不是说要把8条背出来。而是说,规则制定了在一些特殊情况下,不允许编译器、指令器对你写的代码进行指令重排,必须保证你的代码的有序性
但是如果没有满足上面的规则,那么就可能会出现指令重排。这8条原则是避免出现指令重排的情况,要求这几个重要的场景下,是按照顺序来,但是8条规则之外,可以随意重排指令。
flag = false;
//线程1
prepare();//准备资源
flag = true;
//线程2
while(flag){
Thread.sleep(1000);
}
execute();//基于准备好的资源执行操作
比如说这个例子,如果用volatile来修饰flag变量,一定可以让prepare()指令在flag=true之前执行这就禁止了指令重排。因为volatile要求的是,volatile前面的代码一定不能指令重拍到其修饰的变量操作后面,volatile后面的代码也不能指令重排到volatile前面。
(1)知道指令重排是什么意思
(2)知道happen-before原则
(3)volatile避免指令重排
【评论区】
1、一个线程内的所有代码是按顺序执行的(单线程中的指令重排,不影响结果)。只有多线程中,才存在指令重排的问题(多线程问题本质上是共享变量的问题)