java - 在java中同时访问 volatile 变量

标签 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 中的示例不应该遇到同样的问题吗?

最佳答案

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

This means that changes to a volatile variable are always visible to other threads. What's more, it also means that when a thread reads a volatile variable, it sees not just the latest change to the volatile, but also the side effects of the code that led up the change.

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

关于java - 在java中同时访问 volatile 变量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48851817/

相关文章:

java - 注入(inject) URL() Spring Autowired

java - 如何处理不完整的文件?获取异常

c - 僵尸进程即使线程仍在运行

django - 将 gevent(或 eventlet)和 prefork worker 与 Celery 一起使用

java - Android - 检测流结束而不是 MediaPlayer 中的连接错误

java - 如果 `set setOpaque(false);`,JWindow 上的 JPanel 不透明 - 为什么?

java - Unsafe.park 与 Object.wait

go - 在监视器 goroutine 中递归发送

java - 锁定中心化交易

java - 如何从一行中过滤掉一些字符串?