有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

使用volatile'status flag'布尔值的java同步?

我已经了解了volatile用法的“状态标志”模式。 它说,如果状态标志不依赖于任何其他状态,我可以在不进行任何同步的情况下使用volatile。它将保证标志对其他线程的可见性。此外,对布尔值的写入是原子的

但是在与other相关的问题中,有人说当只有一个线程可以修改标志时,使用volotile是安全的。否则,我需要使用任何同步或AtomicBoolean

在我的示例中,我有stopped标志,但它可以在一个线程内进行多次修改:方法stop()continue()。{}不更新任何状态。如果假设stop()continue()方法之后调用stop()时可以不工作,那么代码是线程安全的吗

class MyClass {
    private volatile boolean stopped;

    public void doWork() {
        while(!stopped) {
            doSmth();
        }
    }

    public void stop() {
        stopped = true;
    }

    public void continue() {
        stopped = false;
    }
}

至于我,应该是这样。如果我错了,你能澄清一下吗


共 (1) 个答案

  1. # 1 楼答案

    volatile只是确保变量的更改对所有线程都可用

    背景:线程可以制作共享变量的本地副本。将这些局部变量的值与全局共享变量同步是volatile的效果

    但是,在单个条目、监视器/关键区域的java环境中,这不会同步

    整个java.util.concurrent工具箱提供了一些功能,比如确保只有一个线程可以更改值等等。如果你想从头开始,你可以用两个变量做一些阻塞的事情:搜索Dijkstra算法

    在这里,我认为^{}对于非阻塞使用可能很好


    如果您想要实现一个全局布尔状态,该状态将暂停在切换(你的stopped)时恢复线程,而不是一些丑陋的忙碌等待

    public void run () {
        while (true) {
            doWork(); 
            try {
                barrier.await();
            } catch (InterruptedException | BrokenBarrierException ex) {
                return;
            }
        }
    }
    

    使用全局^{}并不是最好的API,因为它与N个预定义的Runnable一起工作