1.数据相关
数据相关:两个操作访问同一个变量,且其中一个操作是写操作,则这两个操作之间存在数据相关。
三种数据相关:写后读、写后写、读后写
△编译器和处理器在重排序时,不会改变存在数据相关的两个操作的执行顺序。这里的数据相关仅针对单个处理器中执行的指令序列和单个线程中执行的操作序列。
2.as-if-serial语义
as-if-seria语义:不管怎么重排序,(单线程)程序的执行结果不能被改变。编译器、runtime和处理器都必须遵守该语义。
△遵守as-if-serial语义,则不能对存在数据相关的操作做重排序。如果操作之间不存在数据相关,这些操作就可以被编译器和处理器重排序。
3.重排序对多线程的影响
class ReorderExample{
int a = 0;
boolean flag = false;
public void writer(){
a = 1; //操作1
flag = true; //操作2
//操作1和2不存在数据相关,编译器和处理器可以对它们重排序
}
public void reader(){
if(flag){ //操作3
int i = a*a; //操作4
//操作3和4不存在数据相关,但存在控制相关
...
}
}
}
假设现有两个线程A和B,A首先执行writer()方法,随后B执行reader()方法。此时,操作1不一定对操作4可见。
错误执行序列1:

错误执行顺序2:

在单线程程序中,对存在控制相关的操作重排序,不会改变执行结果。但在多线程程序中,对存在控制相关得而操作重排序,可能改变程序的执行结果。
结论:在多线程程序中,重排序可能导致程序执行结果与预期结果的不同。