![](/img/trans.png)
[英]how to fix ConcurrentModificationExceptions in multi-threaded environment?
[英]How to swap boolean value in multi-threaded environment?
1。
volatile boolean bool = false;
// ...
bool = !bool;
2。
volatile AtomicBoolean bool= new AtomicBoolean(false);
// ...
bool.set(!bool.get());
如果有多个线程正在运行,并且其中一个线程需要交换bool
的值并使新值对其他线程可见,那么这两种方法是否具有允许另一个线程的操作发生在读取和写,或AtomicBoolean
确保在调用.get()
和.set()
之间不会发生任何事情?
AtomicBoolean
无法确保get()
和set()
之间不会发生任何事情。
您可以创建3个方法get()
, set()
和swap()
,它们在同一个对象上同步。
你可以尝试这样的事情:
public class SyncBoolean
{
public SyncBoolean()
{
value = false;
}
public synchronized boolean get()
{
return (value);
}
public synchronized void set(boolean newValue)
{
value = newValue;
}
public synchronized void swap()
{
value = !value;
}
private boolean value;
} // class SyncBoolean
由于您给出的原因,两个版本都可能失败。 一种选择是:
boolean b;
do {
b = bool.get();
} while (! bool.compareAndSet(b, !b));
bool = !bool
和bool.set(!bool.get())
都不是原子的。 将操作包装到synchronized块有帮助,因为两个线程无法在同一对象上输入两次。
synchronized(this) {
bool.set(!bool.get());
}
正如已经提到的,你不能简单地在一行中使用volatile boolean或AtomicBoolean来交换值。
有两种方法可以做到,上面也显示了:
虽然第一个解决方案看起来更容易并且正常工作,但在我看来,在大多数情况下,它会被认为是一种不好的做法,应该避免使用。 除非您通过多个线程对此字段的同步修改计数非常高,否则第二个解决方案应该优于第一个解决方案。
然而,如果你真的喜欢简单,并且不需要知道这个决定成本的更好表现,那就选择第一个。
为了添加我的贡献,我注意到你已经将你的原子变量定义为volatile
,并且,以防万一,警告你,如果你不重新分配这个字段并且它可以成为final
,那么最好做到final
。 volatile
仅适用于实际的字段值,如果你不改变它(你没有使用AtomicBoolean
set/compareAndSet
方法)并且你已经确定,其他线程将看到初始化的值( final
是这样的)没有使用它很有意义。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.