volatile传递性

先上代码

static int x = 0;
volatile static int y = 0;

public void actor1(I_Result r) {
    while (y == 0) { //B部分 //C部分

    }
    r.r1 = x + y; //C部分
}

 public void actor2(I_Result r) {
     x = 1;//A部分
     y = 1;//A部分 //B部分
 }

x变量无volatile修饰
y变量有volatile修饰

这里,我把这段代码重点标记三个部分
A部分:12行+13行
B部分:13行+5行
C部分:5行+8行

假设线程t1 执行actor1方法,线程t2,执行actor2方法

先看A部分,由于y变量有volatile修饰,所以A部分的12行和13行不会发生指令重排
再看B部分,由于y变量有volatile修饰,第5行的while循环在y的值改变后一定会读取到最新的1,导致while循环结束。
再看C部分,当程序运行到第8行,获取x+y的结果时,这个结果会是几?

问题已经有了,我们先分析 首先这个y一定是1,因为程序能执行到第8行时,y的值必定不是0了。这是肯定的。那么现在的问题就是x是几
结果是x一定是1
原因就是 volatile具有传递性,如果  x hb-> y 并且  y hb-> z 那么有  x hb-> z ,配合 volatile 的防指令重排

分析一下:

  1. y的值改变在x之后,不会发生指令重排
  2. t2线程改变y=1一定是对t1线程可见的。所以t1线程一定能获取到1

根据传递性

A部分12行,13行代码符合 x(12行) hb-> y(13行)

B部分13行,5行代码符合 y(13行) hb-> z(5行)

C部分5行,8行代码就一定符合 x(5行) hb-> z(8行)

也就是说当t2的y=1对t1线程可见,那么t2的x=1也一定对t1可见,所以x+y结果一定是2。

但是 如果把actor2方法x,y的赋值顺序颠倒

public void actor2(I_Result r) {
        y = 1;//A部分 //B部分
        x = 1;//A部分 
    }

A部分就不符合  x hb-> y ,传递性被破坏,那么C部分读取的x的值就有可能是0。

分析结束,测试一下,这里我就直接上结果了

确实有几率出现x+y=1的情况,说明x的值读取到0的情况。证实了volatile传递性。

如有问题,请指出,我也是刚学习多线程的小白

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值