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

时间:2017-02-10 08:42:38

标签: java multithreading synchronization atomic context-switch

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

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

Atomic Boolean isChannelActive = new AtomicBoolean(false);

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

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()

所以在这种情况下,我的原子布尔值将为true,我会错过notifyAll()事件,因为上下文切换,它将永远等待。

如何防止此问题?

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

2 个答案:

答案 0 :(得分:2)

如果您正在致电wait(),那么您已经> synchronized阻止 。您的方案是假设的,因为调用wait()notifyAll()的线程必须已获得相同的对象监视器。

因此,在你声称的地方有一个上下文切换是不可能的[1]。在这里使用AtomicBoolean也没有优势(至少基于你已经展示的内容),一个简单的volatile boolean也可以正常工作。

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

答案 1 :(得分:2)

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

  1. wait/notify - 这是一个古老的系统,您不再需要使用它。您可以使用wait/notifysynchronized来完成Lock的所有操作。

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

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

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

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

  6. 您尝试同时使用atomicswait/notify。这不会没有困难。

    您可能只需要Lock

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