先行发生关系(happens-before)

分三个层次吧:

第一层次:单个对象或单个方法层次

a.程序次序规则:可以理解为某一线程中的run方法执行代码,控制流书写在前的一定先行于书写在后的,当然,是广义的书写,考虑循环及判断

b.管程锁定规则:可以理解为被锁的(比如synchronized锁定的)程序块中,执行时间在前的先行于执行时间在后的

c.volatile规则:对一个volatile的写执行先行于时间上位于后面的对这个变量的读操作

d.对象的构造方法先行于finalize的开始

注意:a指的是书写次序、b和c指的是时间次序,这个是不一样的,a指单线程内,而b和c可以看作不同线程内执行的时间前后

 

第二层次:线程层次:

e.线程启动先行于线程内的执行

f.线程执行先行于线程终止

g.对线程interrupt()方法的调用先行于中断事件的发生

 

第三个层次:传递原则:

若A先行于B,B先行于C,则A先行于C

 

符合先行发生关系的逻辑由系统保证多线程的逻辑同步,不需要自己控制

 

有一个注意点:先行发生关系并不是CPU指令集上的前后顺序,或者说并非实际执行的先后顺序。怎么理解呢?符合先行发生关系的逻辑:A先行于B,以Java为例,JVM保证若B用到了A的数值或结果,则该数值或结果,A一定先行于B,若A、B并无必然的联系,从JVM层面,A、B甚至是可以互换的。再举一个例子可能更好理解一些:代码的书写次序:

    {

        int a = 1; //A

        int b = 2; //B

        int c = a + b; //C

    }

A先行于C,B也先行于C,A、B并无必然的次序,在字节码层面,执行的次序可能为A->B->C,也可能是B->A->C

在理想的内存模型中,一定是A->B->C,但JVM为了运行优化,可能会对A、B进行交换。

有一个办法可以阻止A、B换位:volatile关键字--被volatile修饰的变量,读不与前交换,写不与后交换

在单线程的环境下,A、B换位并不会影响程序运行结果,而在多线程的环境下,因A、B换位可能会引发一些非所期望的结果,要加倍关注。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值