java - 为什么指令重新排序的 volatile 发生前顺序失败?

标签 java multithreading volatile

我有以下代码来测试 volatile bEndnCount 被定义为 volatile 的。

nCount = 0, bEnd = false

Writer 线程将设置

nCount = 100, bEnd = true

Reader 线程读取这些 viviable 并打印它们。基于 Java Happens-before 顺序,在我看来,当 bEnd = true 时,volatile 确保 nCount = 100。但有时程序会打印以下内容:

main thread done.
thread Reader running ...
thread Writer running ...
SharedData nCount = 0, bEnd = false
thread Writer bEnd = true
thread Reader nCount = 0, bEnd = true
thread Reader nCount = 100, bEnd = true
thread Reader nCount = 100, bEnd = true
thread Reader done.

Reader如何获得“nCount = 0,bEnd = true”???

以下代码在windows10、jdk1.8.0_131上运行

public class HappensBeforeWithVolatile {

    public static void main(String[] args) {

        Thread threadWriter = new Thread(new Writer());
        Thread threadReader = new Thread(new Reader());
        threadWriter.start();
        threadReader.start();

        System.out.println("main thread done.");
    }
}

class Writer implements Runnable {

    @Override
    public void run() {
        System.out.println("thread Writer running ...");
        SharedData.nCount = 100;
//        System.out.println("thread Writer nCount = 100");
        SharedData.bEnd = true;
        System.out.println("thread Writer bEnd = true");
    }
}

class Reader implements Runnable {

    @Override
    public void run() {
        System.out.println("thread Reader running ...");
        System.out.println("thread Reader nCount = " + SharedData.nCount + ", bEnd = " + SharedData.bEnd);
        System.out.println("thread Reader nCount = " + SharedData.nCount + ", bEnd = " + SharedData.bEnd);
        if (SharedData.nCount == 0 && SharedData.bEnd) {
            System.out.println("thread Reader CODE REORDER !!!");
        }
        System.out.println("thread Reader nCount = " + SharedData.nCount + ", bEnd = " + SharedData.bEnd);
        System.out.println("thread Reader done.");
    }
}

class SharedData {
    volatile public static boolean bEnd = false;
    volatile public static int nCount = 0;

    static {
        System.out.println("SharedData nCount = " + nCount + ", bEnd = " + bEnd);
    }
}

最佳答案

当 bEnd = true 时, volatile 确保 nCount = 100

从技术上来说,是的。但读者并没有自动地阅读它们。因此它可能会打印 nCount = 0 和 bEnd = true

这是一个例子:

  1. 读取器读取nCount 0
  2. Wirter 写道 nCount = 100
  3. Wirter 写道 bEnd = true
  4. Writer 打印 thread Writer bEnd = true
  5. 读者读取bEnd true

关于java - 为什么指令重新排序的 volatile 发生前顺序失败?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51742302/

相关文章:

java - 向 LAN 中的每个人发送 UDP 数据包?

java - 将自定义二维数组打印为矩阵

python - 在 python 中,如果持有锁,则暂时释放锁

c - 在 C 中所有使用 volatile 关键字的地方

c++ - C++成员函数声明中volatile关键字的位置

java - JTextField getText() NullPointerException

java - 如果给方法赋予相同的名称怎么办?

java - 几秒后自动更改 jSlider

java - DeepLearning4j k-均值非常慢

java - 在 Java 中使子类中的变量可变