首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >两个BlockingQueue - deadlock

两个BlockingQueue - deadlock
EN

Stack Overflow用户
提问于 2009-09-30 06:41:51
回答 4查看 2K关注 0票数 2

我需要自动操作两个队列,但不确定正确的同步策略是什么:这就是我正在尝试的:

代码语言:javascript
复制
public class transfer {

    BlockingQueue firstQ;
    BlockingQueue secondQ;

    public moveToSecond() {
        synchronized (this){
            Object a = firstQ.take();
            secondQ.put(a)
        }
    }

    public moveToFirst() {
        synchronized(this) {
            Object a = secondQ.take();
            firstQ.put(a);
        }
    }
}

这是正确的模式吗?在方法moveToSecond()中,如果firstQ为空,该方法将等待firstQ.take(),但它仍然持有此对象的锁。这将阻止moveToFirst()有机会执行。

我对等待期间的锁释放感到困惑-线程是否会同时释放这个锁和BlockedQUeue锁??提供原子性来处理多个阻塞队列的正确模式是什么?

EN

回答 4

Stack Overflow用户

发布于 2009-09-30 12:08:41

您使用了正确的方法,使用通用的互斥锁在两个队列之间进行同步。但是,为了避免您描述的第一个队列为空的情况,我建议重新实现moveToFirst()moveToSecond()以使用poll()而不是take()

代码语言:javascript
复制
public void boolean moveToFirst() {
  // Synchronize on simple mutex; could use a Lock here but probably
  // not worth the extra dev. effort.
  synchronzied(queueLock) {
    boolean success;

    // Will return immediately, returning null if the queue is empty.
    Object o = firstQ.poll();

    if (o != null) {
      // Put could block if the queue is full.  If you're using a bounded
      // queue you could use add(Object) instead to avoid any blocking but
      // you would need to handle the exception somehow.
      secondQ.put(o);
      success = true;
    } else {
      success = false;
    }
  }

  return success;
}
票数 2
EN

Stack Overflow用户

发布于 2009-12-17 05:51:36

你没有提到的另一个失败条件是,如果firstQ不为空,但secondQ已满,则该项将从firstQ中删除,但将没有地方放置它。

因此,唯一正确的方法是使用具有超时和代码的轮询和提供,以将事物恢复到任何失败之前的状态(重要!),然后在随机时间后重试,直到轮询和提供都成功。

这是一种乐观的方法;在正常操作中很有效,但在死锁频繁时效率很低(平均延迟取决于所选的超时)

票数 1
EN

Stack Overflow用户

发布于 2009-09-30 06:51:43

您应该使用java.util.concurrency中的锁定机制,如下所示:

代码语言:javascript
复制
Lock lock = new ReentrantLock();
....
lock.lock();
try {
    secondQ.put(firstQ.take());
} finally {
    lock.unlock();
}

对firstQ.put(secondQ.take())执行相同的操作,使用相同的锁对象。

不再需要在Object类上使用低级等待/通知方法,除非您正在编写新的并发原语。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/1496439

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档