繁体   English   中英

如何在多线程环境中交换布尔值?

[英]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 = !boolbool.set(!bool.get())都不是原子的。 将操作包装到synchronized块有帮助,因为两个线程无法在同一对象上输入两次。

synchronized(this) {
    bool.set(!bool.get());
}

正如已经提到的,你不能简单地在一行中使用volatile boolean或AtomicBoolean来交换值。

有两种方法可以做到,上面也显示了:

  • 使用一个“全局”锁定/同步
  • via while循环和AtomicBoolean.compareAndSet

虽然第一个解决方案看起来更容易并且正常工作,但在我看来,在大多数情况下,它会被认为是一种不好的做法,应该避免使用。 除非您通过多个线程对此字段的同步修改计数非常高,否则第二个解决方案应该优于第一个解决方案。

然而,如果你真的喜欢简单,并且不需要知道这个决定成本的更好表现,那就选择第一个。

为了添加我的贡献,我注意到你已经将你的原子变量定义为volatile ,并且,以防万一,警告你,如果你不重新分配这个字段并且它可以成为final ,那么最好做到final volatile仅适用于实际的字段值,如果你不改变它(你没有使用AtomicBoolean set/compareAndSet方法)并且你已经确定,其他线程将看到初始化的值( final是这样的)没有使用它很有意义。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM