多线程应用程序中的原子布尔值用法

Atomic Boolean usage in multithreaded application

我正在尝试 运行 以下代码:

在我的构造函数中,我初始化了我的原子布尔值:

Atomic Boolean isChannelActive = new AtomicBoolean(false);

在我的写入方法中,我检查了这个布尔值并等待:

public ChannelFuture write(ByteBuf msgBuf) {
if (!isChannelActive.get()) {
  try {
    wait();
  } catch (InterruptedException ex) {
    logger.Error("Waiting interrupted", ex);
  }
}

但问题是这个原子布尔值可以在程序运行时从不同的线程设置:

if (!isChannelActive.get()) { 
  try{ --- Right on here and program made a context switch at this time.
    wait()

所以在这种情况下,我的原子布尔值将为真,我错过了 notifyAll() 事件,并且由于上下文切换将永远等待。

我怎样才能避免这个问题?

我知道同步块可能是一个选项,但我正在为这种情况寻找更优雅的选项。

如果您正在调用 wait(),那么您已经 一个 synchronized 块中。您的场景是一个假设场景,因为调用 wait()notifyAll() 的两个线程必须获得相同的对象监视器。

因此,您声明的地方不可能存在上下文切换[1]。在这里使用 AtomicBoolean 也没有任何优势(至少根据您所展示的内容),一个简单的 volatile boolean 也可以。

[1] 并非不可能,您可以编写代码以便在同步块之外进行条件检查,但那将是故意编写损坏的并发代码。

您不应混合使用不同级别的同步机制。

  1. wait/notify - 这是一个您不再需要使用的陈旧系统。用 wait/notify 可以做的一切都可以用 synchronizedLock 来完成。

  2. synchronized - 这允许您同步代码,以便需要独占访问的部分不会相互干扰。

  3. Locks - 有各种不同类型的锁,通常可以处理您喜欢的几乎任何访问控制。

  4. Blocking... - 这是更现代的方法 - 它使用数据结构来确保安全访问,而不是将同步放在代码中。

  5. 还有更多的功能集,例如 PhaserSemaphore 可用于实现一些更常见的机制。

您正试图同时使用 atomicswait/notify。这不会没有困难。

您可能只需要 Lock.

Lock channelActive = new ReentrantLock();

public void test() {
    channelActive.lock();
    try {
        // Do your exclusive stuff here.
    } finally {
        channelActive.unlock();
    }

}