指令重排序

指令重排序

指令的基本概念

    指令是指示计算机执行某种操作的命令,如:数据传送指令、算术运算指令、位运算指令、程序流程控制指令、串操作指令、处理器控制指令。指令不同于我们所写的代码,一行代码按照操作的逻辑可以分成多条指令。

     举个例子:int a = 1;  这段代码大致可以分为两条指令:1.加载常量1;2.将常量1赋值给变量a。

 

指令重排序

    Java语言规范JVM线程内部维持顺序花语义,即只要程序的最终结果与它顺序化情况的结果相等,那么指令的执行顺序可以与代码逻辑顺序不一致,这个过程就叫做指令的重排序。

    指令重排序的意义:使指令更加符合CPU的执行特性,最大限度的发挥机器的性能,提高程序的执行效率。

 

源代码到最终执行的指令序列示意图

指令重排序主要分为三种:

1.编译器重排序:JVM中进行完成的

2.指令级并行重排序

3.处理器重排序:CPU中进行完成的

 

As-If-Serial语义

    as-if-serial语义的意思是:不管怎么进行指令重排序,单线程内程序的执行结果不能被改变。编译器,处理器进行指令重排序都必须要遵守as-if-serial语义规则。

    为了遵守as-if-serial语义,编译器和处理器对存在依赖关系的操作,都不会对其进行重排序,因为这样的重排序很可能会改变执行的结果,但是对不存在依赖关系的操作,就有可能进行重排序。

 

Happens-Before原则

    happens-before可以理解为“先于”,是用来指定两个操作之间的执行顺序,由于这个两个操作可以在一个线程之内,也可以在不同线程之间。因此,JMM可以通过happens-before关系来保证跨线程的内存可见性(如果A线程是对变量进行写操作,而B线程是对变量进行读操作,那么如果A线程是先于B线程的操作,那么A线程写操作之后的数据对B线程也是可见的)

具体的定义:

    1.如果一个操作“先于”另一个操作,那么第一操作的执行结果将对第二个操作可见,而且第一个操作的执行顺序排在第二个操作之前;

    2.两个操作是happens-before的关系,也并不意味着JVM会按照这个关系去顺序执行,因为会存在重排序的可能,但是进行了重排序的执行结果,与此happens-before的关系顺序执行的结果一致的话,那就说明这个重排序是合法的(也就是JVM允许这样的重排序)。

 

具体规则:

    1.程序顺序规则:在一个线程内必须保证语义串行性,也就是按照代码顺序执行;

    2.监视器(管程)锁规则:无论是单线程还是对线程环境,对于同一个锁来说,解锁操作必须是先于后一个加锁操作之前(如果A线程进行了加锁,还未进行解锁,那么B线程是不可能进行加锁操作的,只有等到A线程进行解锁操作之后,才能再进行加锁操作),而且前者线程解锁之后,对数据的操作对于后者加锁的线程是可见的;

    3.volatile规则:volatile变量的写先于变量的读,保证了volatile变量的可见性,简而言之,volatile变量每次别线程访问时,都强迫从主内存中读该变量的值,而当变量的值被修改时,又会强迫将最新的值从工作内存刷回主内存中,任何时刻,不同线程总是能获取到该变量的最新值;

    4.线程启动规则:线程的start方法先于此线程run方法中的所有操作(线程一定是执行start方法之后,才会执行真正的run方法逻辑),如果A线程在执行过程中,执行B线程的start方法,那么在A线程执行过程中到B线程start这一段区域中对共享变量的修改,对线程B是可见的;

    5.线程终止规则:线程run方法中的执行操作一定是先于此线程的join方法的,如果B线程修改了共享变量的值,那么在B线程执行join方法之后,主线程一定对此共享变量是可见的;

    6.线程中断规则:对线程 interrupt()方法的调用先行发生于被中断线程的代码检测到中断事件的发生,可以通过Thread.interrupted()方法检测线程是否中断;

    7.传递性:A先于B,B先于C,那么一定可以知道A先于C;

    8.对象终结规则:一个对象的初始化完成(构造函数执行完成)一定先于finalize方法(对象被回收时会调用,即垃圾回收时)之前执行,也就是现有对象才能进行对象回收操作。

 

 

As-if-Serial 和 Happens-Before原则

1. as-if-serial语义保证单线程内程序的执行结果不被改变,happens-before关系保证正确同步的多线程程序的执行结果不被改变;

2.as-if-serial语义给编写单线程程序的程序员创造了一个幻境:单线程程序是按程序的顺序来执行的。happens-before关系给编写正确同步的多线程程序的程序员创造了一个幻境:正确同步的多线程程序是按happens-before指定的顺序来执行的;

3.as-if-serial语义和happens-before这么做的目的,都是为了在不改变程序执行结果的前提下,尽可能地提高程序执行的并行度。

符合Happens-before规则的多线程程序才是正确的逻辑,符合As-if-serial语义的单线程程序才是正确的逻辑,这也是保证了程序员对代码编写的逻辑合理性。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值