as-if-serial

重排的异常

多线程的重排
执行程序时,为了提供性能,处理器和编译器常常会对指令进行重排序,但是不能随意重排序,不是你想怎么排序就怎么排序,它需要满足以下两个条件:
  • 在单线程环境下不能改变程序运行的结果;
  • 存在数据依赖关系的不允许重排序

as-if-serial

所有的操作均可以为了优化而被重排序,但是你必须要保证重排序后执行的结果不能被改变,编译器、runtime、处理器都必须遵守as-if-serial语义。注意as-if-serial只保证单线程环境,多线程环境下无效。

重排的异常
异常发生点之前的代码被重排到发生点之后,那如何保证执行结果?


public class RecordExample1 {
    public static void main(String[] args){
        int a = 1;
        int b = 2;

        try {
            a = 3;           //A
            b = 1 / 0;       //B
        } catch (Exception e) {
            
        } finally {
            System.out.println("a = " + a);
        }
    }
}

按照重排序的规则,操作A与操作B有可能会进行重排序,如果重排序了,B会抛出异常( / by zero),此时A语句一定会执行不到,那么a还会等于3么?如果按照as-if-serial原则它就改变了程序的结果。其实JVM对异常做了一种特殊的处理,为了保证as-if-serial语义,Java异常处理机制对重排序做了一种特殊的处理:JIT在重排序时会在catch语句中插入错误代偿代码(a = 3),这样做虽然会导致cathc里面的逻辑变得复杂,但是JIT优化原则是:尽可能地优化程序正常运行下的逻辑,哪怕以catch块逻辑变得复杂为代价。

多线程的重排

重排序不会影响单线程环境的执行结果,但是会破坏多线程的执行语义。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值