我需要自动操作两个队列,但不确定正确的同步策略是什么:这就是我正在尝试的:
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锁??提供原子性来处理多个阻塞队列的正确模式是什么?
发布于 2009-09-30 12:08:41
您使用了正确的方法,使用通用的互斥锁在两个队列之间进行同步。但是,为了避免您描述的第一个队列为空的情况,我建议重新实现moveToFirst()和moveToSecond()以使用poll()而不是take();
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;
}发布于 2009-12-17 05:51:36
你没有提到的另一个失败条件是,如果firstQ不为空,但secondQ已满,则该项将从firstQ中删除,但将没有地方放置它。
因此,唯一正确的方法是使用具有超时和代码的轮询和提供,以将事物恢复到任何失败之前的状态(重要!),然后在随机时间后重试,直到轮询和提供都成功。
这是一种乐观的方法;在正常操作中很有效,但在死锁频繁时效率很低(平均延迟取决于所选的超时)
发布于 2009-09-30 06:51:43
您应该使用java.util.concurrency中的锁定机制,如下所示:
Lock lock = new ReentrantLock();
....
lock.lock();
try {
secondQ.put(firstQ.take());
} finally {
lock.unlock();
}对firstQ.put(secondQ.take())执行相同的操作,使用相同的锁对象。
不再需要在Object类上使用低级等待/通知方法,除非您正在编写新的并发原语。
https://stackoverflow.com/questions/1496439
复制相似问题