【问题标题】:Synchronization with volatile 'status flag' boolean?与易失性“状态标志”布尔值同步?
【发布时间】:2019-11-19 20:29:44
【问题描述】:

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

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

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

class MyClass {
    private volatile boolean stopped;

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

    public void stop() {
        stopped = true;
    }

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

对我来说,它应该。如果我错了,你能澄清一下吗?

【问题讨论】:

  • 你没有使用 volatile。没有人知道doSmth 是什么。如果您只有一个布尔变量“停止”,请确保它是线程安全的。
  • 代码看起来不错。你在哪里读到volatile 不适用于这个用例?您链接的线程上接受的答案完全将您的场景作为volatile的良好用途。
  • 你是对的,我错过了示例中的 volatile 修饰符。 doSmth() 只是做一些与标志无关的事情。我已经更新了描述。
  • @matt,您写道:如果您只有一个布尔变量“停止”,请确保它是线程安全的。非易失性布尔值不能保证其他线程的可见性,我可以在 doWork() 中有无限循环。我相信它不可能是线程安全的。
  • @Thilo,我已经更新了答案的链接。据我了解,如果我们从 > 1 个线程进行修改,它可能不是线程安全的。另外,这不是我的陈述,如果我理解正确,这更像是一个问题。

标签: java multithreading atomicboolean


【解决方案1】:

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

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

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

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

这里我认为AtomicBoolean 可能适合非阻塞使用。


如果您想获得一个暂停的全局布尔状态。切换时恢复线程(您的stopped),而不是一些丑陋的忙等待

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

使用全局 CyclicBarrier - 不是最好的 API,因为它与 N 个预定义的 Runnables 一起使用。

【讨论】:

  • 对于一个简单的“线程应该停止”标志,在这种情况下,volatile boolean 似乎就足够了。它也没有阻塞。但是,是的,一般来说,这种代码太低级了。如今,没有人应该直接管理线程。并发工具中是否有一些简单的“重复运行直到我说停止”?
  • @Joop Eggen,感谢您的回答。我的想法是,除了原始布尔标志之外,我这里没有任何关键部分。但由于布尔读/写是原子的,我不必在这里进行任何同步,即使我从许多线程中修改它。 volatile 将使每个线程从主内存中查看 volatile 布尔值。如果我错了,请告诉我。
  • @Thilo thread.interrupt()threadGroup.interrupt() 以获得友好的结局。然后ExecuterService.shutdown, shutdownNow, awaitTermination
  • @androberz 如果doWorkrun 所做的,那么线程肯定会在第一个stopped 设置为true 之后结束;我会添加代码。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-02-10
  • 1970-01-01
  • 1970-01-01
  • 2015-04-08
  • 2023-03-15
相关资源
最近更新 更多