Java多线程环境下可能会出现指令重排的代码示例
什么是指令重排?
我们在执行程序时,为了提高性能,编译器和处理器某些情况下会对指令进行重排序。
as-if-serial语义
不管怎么重排序,不能影响单线程环境下的执行结果,这是as-if-serial语义定义的,编译器和处理器阶段的重排都遵循该规则。
编译器和处理器都遵循的指令重排的原则
a、数据依赖,只对不存在数据依赖的指令进行重排。
b、控制依赖,允许对有控制依赖关系的指令做重排。
Java多线程环境下可能会出现指令重排的代码示例
既然有了上面两个指令重排的前提,我们就可以根据这些规则写一个demo来实际测验出指令重排。
public class SysParamEnumController { private volatile int a = 0; private volatile int b = 0; private volatile boolean flag = false; // 此方法里的三个指令没有数据依赖关系 public void write() { a = 1; b = 2; flag = true; } // 此方法里的if就是控制依赖关系 public void render() { if (flag) { System.out.println(a * b); } else { System.out.println("-1"); } } public static void main(String[] args) throws InterruptedException { for (int i = 0; i < 1000; i++) { SysParamEnumController sysParamEnumController = new SysParamEnumController(); Thread t1 = new Thread(() -> { sysParamEnumController.write(); }); Thread t2 = new Thread(() -> { sysParamEnumController.render(); }); t1.start(); t2.start(); t1.join(); t2.join(); } } }
结果
出现了-1就代表受到了指令重排的影响,因为指令重排只会小概率出现,所以我循环了1000次。
