Java 与volatile'同步;状态标志';布尔值?

Java 与volatile'同步;状态标志';布尔值?,java,multithreading,atomicboolean,Java,Multithreading,Atomicboolean,我已经读过关于volatile用法的“状态标志”模式。 它说,如果状态标志不依赖于任何其他状态,我可以在不进行任何同步的情况下使用volatile。它将保证标志对其他线程的可见性。此外,对布尔值的写入是原子的 但是在相关的问题中,有人说当只有一个线程可以修改标志时,使用volotile是安全的。否则,我需要使用任何同步或AtomicBoolean 在我的示例中,我有stopped标志,但它可以在一个线程内进行多次修改:方法stop()和continue()。doSmth()不会更新任何状态。如果

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

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

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

class MyClass {
    private volatile boolean stopped;

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

    public void stop() {
        stopped = true;
    }

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

至于我,应该是这样。您能澄清一下我是否错了吗?

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

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

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

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

在这里,我认为对于非阻塞使用可能是很好的


如果您想要实现一个全局布尔状态,暂停resp在切换(您的
已停止
)时恢复线程,而不是一些丑陋的繁忙等待:


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

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

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

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

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

在这里,我认为对于非阻塞使用可能是很好的


如果您想要实现一个全局布尔状态,暂停resp在切换(您的
已停止
)时恢复线程,而不是一些丑陋的繁忙等待:


使用全局-不是最好的API,因为它与N预定义的
Runnable
s一起工作。

您没有使用volatile。没有人知道什么是
doSmth
。如果您只是有一个布尔变量“stopped”,请确保它是线程安全的。代码看起来很好。您在哪里读到
volatile
不适用于此用例?你链接的线程上的公认答案准确地假设你的场景是
volatile
的一个很好的用法。你是对的,我错过了示例中的volatile修饰符。doSmth()只是执行与标志无关的操作。我已经更新了描述。@matt,您写道:如果您只有一个布尔变量“stopped”,请确保它是线程安全的。非易失性布尔函数不能保证其他线程的可见性,我可以在doWork()中使用无限循环。我相信它不可能是线程安全的。@Thilo,我已经更新了答案的链接。正如我从中了解到的,如果我们修改了>1个线程,那么它可能不是线程安全的。另外,这不是我的声明,如果我理解正确,这更像是一个问题。你没有使用volatile。没有人知道什么是
doSmth
。如果您只是有一个布尔变量“stopped”,请确保它是线程安全的。代码看起来很好。您在哪里读到
volatile
不适用于此用例?你链接的线程上的公认答案准确地假设你的场景是
volatile
的一个很好的用法。你是对的,我错过了示例中的volatile修饰符。doSmth()只是执行与标志无关的操作。我已经更新了描述。@matt,您写道:如果您只有一个布尔变量“stopped”,请确保它是线程安全的。非易失性布尔函数不能保证其他线程的可见性,我可以在doWork()中使用无限循环。我相信它不可能是线程安全的。@Thilo,我已经更新了答案的链接。正如我从中了解到的,如果我们修改了>1个线程,那么它可能不是线程安全的。另外,这不是我的陈述,如果我理解正确的话,这更像是一个问题。对于一个简单的“线程应该停止”标志,如本例所示,
volatile boolean
似乎足够了。它也不是阻塞。但是,是的,一般来说,这种代码太低级了。现在不应该有人直接管理线程。concurreny utils中是否有“重复运行直到我说停止”的简单说法?@Joop Eggen,谢谢你的回答。我的想法是,除了原始布尔标志,这里没有任何关键部分。但是由于布尔读/写是原子的,所以我不必在这里进行任何同步,即使我从许多线程修改它。volatile将使每个线程从主内存中看到volatile布尔值。如果我错了,请告诉我。@Thilo
thread.interrupt()
threadGroup.interrupt()
,以获得友好的结局。然后@androberz如果
doWork
run
public void run () {
    while (true) {
        doWork(); 
        try {
            barrier.await();
        } catch (InterruptedException | BrokenBarrierException ex) {
            return;
        }
    }
}