当前位置: 首页 > 知识库问答 >
问题:

Volatile变量的更新值对其他线程不可见

伊光赫
2023-03-14

下面的代码片段使用多个线程,使用AtomicInteger计算到1亿。我有10个Writer线程来模拟写争用,还有一个Reader线程来模拟读争用。作者和读者还共享一个易变的布尔变量作为毒药。

但是,只有读线程可以退出,而写线程不能退出。尽管将变量声明为volatile,但为什么读线程不能看到更新的值?

public class AtomicRunnerV2 {

    private static final int THREADS = 10;
    private static final Integer MAX_COUNT = 100_000_000;

    public static void main(String[] args) throws Exception {
        AtomicInteger atomicInteger = new AtomicInteger(1);
        Boolean data = new Boolean(false);
        ExecutorService executorService = Executors.newFixedThreadPool(THREADS + 1);
        for (int i = 0; i < THREADS; i++) {
            executorService.submit(new Writer(atomicInteger, data));
        }
        executorService.submit(new Reader(atomicInteger, data));
        executorService.shutdown();
    }

    static class Writer implements Runnable {

        private AtomicInteger integer;
        private volatile Boolean data;

        Writer(final AtomicInteger integer, Boolean data) {
            this.integer = integer;
            this.data = data;
        }

        @Override public void run() {
            while (!data) {
                integer.incrementAndGet();
            }
            System.out.println("count " + integer.get() + " from WRITER!");
        }
    }

    static class Reader implements Runnable {

        private AtomicInteger integer;
        private volatile Boolean data;

        Reader(final AtomicInteger integer, Boolean data) {
            this.integer = integer;
            this.data = data;
        }

        @Override public void run() {
            while (!data) {
                if (integer.get() >= MAX_COUNT) {
                    data = true;
                }
            }
            System.out.println("count " + integer.get() + " from READER!");
        }
    }
}

附言:如果我把布尔值包在一个对象中,它就会工作。

共有2个答案

彭鹭洋
2023-03-14

布尔是不变的。

data = true;

Writer中的上述行实质上创建了一个新的布尔实例,从而导致读者永远看不到新值,因为他们的布尔引用中没有任何内容“更新”。

通过用下面这样的自定义类替换代码中的所有布尔值,读者线程能够看到更新后的值来测试这一点。

static class MyBoolean {

    private boolean value;

    MyBoolean(final boolean value) {
        this.value = value;
    }

    boolean isValue() {
        return value;
    }

    void setValue(final boolean value) {
        this.value = value;
    }
}
满增
2023-03-14

您的volatile boolean数据不是一个参考,我想您在这里试图建议,而是一个副本。所以读卡器中的数据永远不会被设置为false。如果你使用Writer。读卡器中的数据(并将其公开),这应该是有效的。

 类似资料:
  • 类OneValueCache是不可变的。但是我们可以更改变量缓存的引用。 但我不能理解为什么VolateCachedFactorizer类是线程安全的。 对于两个线程(线程A和线程B),如果线程A和线程B同时到达,那么两个线程A和B都将尝试创建OnEvalueCache。然后线程A到达而线程B同时到达。然后线程A将创建一个,它覆盖threadB创建的值(OneValueChange是不可变的,但是

  • null 我的问题是--第二点是真的吗?即。我可以仅仅通过在易失性引用中存储对对象的引用来使它的状态对其他线程可见吗?如果不是,我是不是读错了上面的几点?

  • 我正在编写一个Android应用程序,它连接到蓝牙设备,读取设备发送的数据,将其添加到AChartEngine图形中,并在文本视图中显示数据。 我的Bluetooth代码与BluetoothChat示例代码中的线程实现非常相似(它与SDK一起提供)。我可以在LogCat中看到< code>ConnectedThread循环正在执行并因此获得新数据,但我的TextView在7行之后停止更新,图形间歇

  • App.js中有一个全局变量,该变量在我的应用程序组件之外设置。 它监视棋盘游戏正在进行的移动。在黑板下面是一些导航按钮。如果您单击

  • 我目前正在学习多线程,我发现了一些我无法解释的有趣的东西。据我所知,如果两个线程访问一个静态变量,它们可以将自己的副本复制到缓存中。Thread1对其本地缓存中的静态变量进行的更新不会反映在Thread2缓存的静态变量中。 java java

  • 我有一个疑问是UI线程和其他线程之间相对并发。 Ui主线程更新不同变量的值:-float-long-boolean 我有另一个线程读取相同的变量并对其进行一些逻辑操作(不编辑其值),并将此操作的结果发送本地广播消息。 是否存在并发问题,我必须使用:同步方法和原子变量,还是无关紧要? 我反思这个问题,因为没有浮点基元的原子变量,也因为我害怕用错误的代码阻止Ui线程... 编辑:其他问题 对于引用变量