什么是指令重排序
CPU的速度至少比内存快100倍,为了提升效率,会打乱原来的执行效率,会在一条指令执行过程中(比如去内存读数据,大概慢100多倍),去同时执行另一条指令(前提是两条指令没有依赖关系)。体现在代码层面
就是,写在后面的代码可能比前面的代码先执行。
验证指令重排序
观察下面代码:
/**
* 测试指令重排序
*/
public class ReorderTest {
private static int x = 0, y = 0;
private static int a = 0, b = 0;
public static void main(String[] args) throws InterruptedException {
int i = 0;
while (true){
i++;
x = 0;
y = 0;
a = 0;
b = 0;
Thread one = new Thread(() -> {
a = 1;
x = b;
});
Thread other = new Thread(() -> {
b = 1;
y = a;
});
one.start();
other.start();
one.join();
other.join();
String result = "第" + i + "次 (" + x + "," + y + ")";
if (x == 0 && y == 0) {
System.err.println(result);
break;
}
}
}
}
如果没有指令重排序,那么对于线程one来说a = 1;一定在x = b;之前执行,对于线程other也是如此。
当两个线程同时执行时,代码的执行顺序只能是以下几种:
第一种 a = 1; x = b; b = 1; y = a;
第二种 b = 1; y = a; a = 1; x = b;
第三种 a = 1; b = 1; x = b; y = a;
第四种 a = 1; b = 1; y = a; x = b;
第五种 b = 1; a = 1; y = a; x = b;
第六种 b = 1; a = 1; x = b; y = a;
而这六种执行顺序最后x、y的结果值为:
第一种 0 1
第二种 1 0
第三种 1 1
第四种 1 1
第五种 1 1
第六种 1 1
可以发现上面的执行顺序不可能出现x、y同时为0的情况,除非发生指令重排序导致下面这种执行顺序:
x = b; y = a; a = 1; b = 1;
实测可以发现运行到第20422次时发生了指令重排序(运行次数可能会不一样)
说明CPU确实发生了指令重排序