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布尔值。如果我错了,请告诉我。@Thilothread.interrupt()
或threadGroup.interrupt()
,以获得友好的结局。然后@androberz如果doWork
是run
public void run () {
while (true) {
doWork();
try {
barrier.await();
} catch (InterruptedException | BrokenBarrierException ex) {
return;
}
}
}