jsr133+java,JSR133给Java内存模型定义的happen-before规则

单线程规则:同一个线程中的每个操作都happens-before于出现在其后的任何一个操作。

对一个监视器的解锁操作happens-before于每一个后续对同一个监视器的加锁操作。

对volatile字段的写入操作happens-before于每一个后续的对同一个volatile字段的读操作。

Thread.start()的调用操作会happens-before于启动线程里面的操作。

一个线程中的所有操作都happens-before于其他线程成功返回在该线程上的join()调用后的所有操作。

一个对象构造函数的结束操作happens-before与该对象的finalizer的开始操作。

传递性规则:如果A操作happens-before于B操作,而B操作happens-before与C操作,那么A动作happens-before于C操作。

实际上这组happens-before规则定义了操作之间的内存可见性,如果A操作happens-before B操作,那么A操作的执行结果(比如对变量的写入)必定在执行B操作时可见。

为了更加深入的了解这些happens-before规则,我们来看一个例子:

//线程A,B共同访问的代码

Object lock = new Object();

int a=0;

int b=0;

int c=0;

//线程A,调用如下代码

synchronized(lock){

a=1; //1

b=2; //2

} //3

c=3; //4

//线程B,调用如下代码

synchronized(lock){  //5

System.out.println(a);  //6

System.out.println(b);  //7

System.out.println(c);  //8

}

我们假设线程A先运行,分别给a,b,c三个变量进行赋值(注:变量a,b的赋值是在同步语句块中进行的),然后线程B再运行,分别读取出这三个变量的值并打印出来。那么线程B打印出来的变量a,b,c的值分别是多少?

根据单线程规则,在A线程的执行中,我们可以得出1操作happens before于2操作,2操作happens before于3操作,3操作happens before于4操作。同理,在B线程的执行中,5操作happens before于6操作,6操作happens before于7操作,7操作happens before于8操作。而根据监视器的解锁和加锁原则,3操作(解锁操作)是happens before 5操作的(加锁操作),再根据传递性 规则我们可以得出,操作1,2是happens before 操作6,7,8的。

则根据happens-before的内存语义,操作1,2的执行结果对于操作6,7,8是可见的,那么线程B里,打印的a,b肯定是1和2. 而对于变量c的操作4,和操作8. 我们并不能根据现有的happens before规则推出操作4 happens before于操作8. 所以在线程B中,访问的到c变量有可能还是0,而不是3.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值