在java中同时访问volatile varibales

时间:2018-02-18 12:43:43

标签: java multithreading concurrency volatile

在阅读this blog post时,我没有理解第3.6和3.7节。

3.6中的代码:

@JCStressTest
@State
public class AcquireOrderWrong {
    int x;
    volatile int g;

    @Actor
    public void actor1() {
        g = 1;
        x = 1;
    }

    @Actor
    public void actor2(IntResult2 r) {
        r.r1 = x;
        r.r2 = g;
    }
}

3.7中的代码:

@JCStressTest
@Outcome(id = "1, 0", expect = Expect.FORBIDDEN,  desc = "Happens-before violation")
@Outcome(             expect = Expect.ACCEPTABLE, desc = "All other cases are acceptable.")
@State
public class SafePublication {

    int x;
    volatile int ready;

    @Actor
    public void actor1() {
        x = 1;
        ready = 1;
    }

    @Actor
    public void actor2(IntResult2 r) {
        r.r1 = ready;
        r.r2 = x;
    }
}

在3.6中,由于它是一个赤裸裸的数据竞赛,因此我认为1,0是一个不可能的结果我可能错误地将其解释为,因为不相关的操作可能是在执行时重新排序,这可能会发生

但如果是这种情况,那么3.7中的例子不应该遭遇同样的问题吗?

1 个答案:

答案 0 :(得分:2)

在3.7中,ready是一个volatile变量,根据doc

  

这意味着对volatile变量的更改始终可见   其他线程。更重要的是,它还意味着当线程读取时   volatile变量,它不仅看到了volatile的最新变化,   但也导致了改变的代码的副作用。

actor()中,您在设置ready后设置x。因此,当您在方法ready中阅读actor2时,JVM可以保证x=1也可见,从而避免(1, 0)作为输出。