请稍等 ...
×

采纳答案成功!

向帮助你的同学说点啥吧!感谢那些助人为乐的人

关于volatile禁止指令重排

问题1
volatile禁止指令重排,那么禁止的时change这个方法那里的重排序?是a = 3不会在b = 3之后吗?如果是的话b = 3前面如果有很多代码都会按照书写顺序执行吗?

int a = 1;
volatile int b = 2;
private void change() {
    a = 3;
    b = 3;
}

private void print() {
    System.out.println("b = " + b + ", a = " + a);
}

问题2
上面的print代码输出的时候是否能够保证a与b都等于3?如果说问题1假设成立的话那么是能够保证的。
但是 https://coding.imooc.com/learn/questiondetail/vQW1lYEEVVmYyE9A.html 这里说“就算b不涉及a,也可以只给b加volatile,因为只要修改了b,那么之前的代码(对a的修改)就可见。”
https://coding.imooc.com/learn/questiondetail/y0K5g681gnmPe2QN.html 这里又说不能保证,实在是搞晕了,求老师解答

正在回答

1回答

1:对于执行change方法的线程而言,是a = 3不会在b = 3之后,因为要满足“单线程内可见性原则”,也就是单线程内看到的,和代码书写顺序是一致的。如果b = 3前面如果有很多代码,这些代码都不会在b=3之后,但是这些代码内部是可以重排序的。

2:我认为https://coding.imooc.com/learn/questiondetail/y0K5g681gnmPe2QN.html这个同学说的是对的,如果加了volatile,那么不管有没有依赖,可见性是可以保证的。我之前的一些解答可能写错了。

0 回复 有任何疑惑可以回复我~
  • 提问者 风刚才唱歌 #1
    那就是说在对volatile修饰的变量的读写操作时,在之前的语句不会重排序到后面;后面的语句不会重排序到前面。但是在保证单线程可见性也就是单线程结果正确的情况下,非volatile修饰的语句仍然会发生重排序。
    或者说对volatile修饰的变量的读写操作就像是在代码中的一个屏障,屏障前面的代码在保证正确的情况下可以重排序但是不会重排序到屏障后;原本在屏障后的代码也不会到屏障前。
    两个对volatile修饰的变量的读写操作也是一样的,屏障前、后以及中间的代码仍然会在正确的前提下排序,但是不会越过每段代码的屏障范围。
    老师我这样理解对吗?
    回复 有任何疑惑可以回复我~ 2021-12-31 20:03:52
  • 悟空 回复 提问者 风刚才唱歌 #2
    是对的
    回复 有任何疑惑可以回复我~ 2022-01-01 11:47:33
  • 提问者 风刚才唱歌 回复 悟空 #3
    好的 谢谢老师
    回复 有任何疑惑可以回复我~ 2022-01-01 13:59:16
问题已解决,确定采纳
还有疑问,暂不采纳
意见反馈 帮助中心 APP下载
官方微信