代码之家  ›  专栏  ›  技术社区  ›  Vijay

同步方法内的BlockedLinkedQueue死锁

  •  1
  • Vijay  · 技术社区  · 15 年前

    这可能是一个新问题-我在使用BlockedLinkedQueue时遇到了死锁情况-下面是我的代码片段:

    public class mytest {
        private BlockedLinkedQueue myQueue;
    
        public synchronized void consumer() {
            ...
            myQueue.take()
            ...
        }
    
        public synchronized void producer() {
            ...
            myQueue.put()
            ...
        }
    }
    

    我注意到有时我会陷入僵局。很多producer()线程在方法监视器上等待,一个consumer在take()上被阻塞。这是预期的吗?我知道我不需要同步BLockedLinkedQUeue,但我有很多其他对象,我需要同步这些方法。。

    2 回复  |  直到 15 年前
        1
  •  8
  •   maxkar    15 年前

    是的,这是预料中的僵局。当使用空队列调用consumer()时发生。在本例中,consumer()持有“this”的锁,并等待来自myQueue的对象。同时,任何producer()都不能锁定“this”(由使用者持有),因此不能将任何对象放入myQueue,这会阻止使用者获取对象。

    要解决死锁,您可以只同步方法的一部分,或者使用简单队列并实现自己的等待数据。 部分同步示例:

    public class mytest {
    private BlockedLinkedQueue myQueue;
    
    public void consumer() {
        synchronized(this) {
            ...
        }
        myQueue.take();
        synchronized (this) {
            ...
        }
    }
    
    public void producer() {
        synchronized(this) {
            ...
        }
        myQueue.put()
        synchronized(this) {
            ...
        }
    }
    }
    

    在这种情况下,myQueue操作期间会释放对“this”的锁定。它将允许producer()按原样进行,并将对象放入队列。

    public class mytest {
    private Queue myQueue;
    
    public synchronized void consumer() {
        ...
        while (myQueue.isEmpty()) {
            this.wait();
        }
        myQueue.take()
        ...
    }
    
    public synchronized void producer() {
        ...
        myQueue.put()
        this.notify();
        ...
    }
    }
    

    在这个例子中,“this”的锁在调用this.wait()期间被释放(有关详细信息,请参见Object.wait()),它允许生产者将对象放入队列。同时,生产者唤醒一个等待数据的消费者。

    请注意,在这两种情况下,producer方法都将在只执行consumer方法的“一半”时执行。一、 消费方法不再是原子的,而只是半原子的。如果您需要使用者的原子性,那么您应该考虑更好地规范生产者/使用者方法,因为所描述的死锁是“同步”中的逻辑缺陷。在执行“atomic”consumer()方法期间不能放置对象,同时consumer()要求对象在队列中。

        2
  •  1
  •   Stu Thompson Helter Scelter    15 年前

    BlockedLinkedQueue ? 我想你是说 LinkedBlockingQueue

    LinkedBlockingQueue

    正如马克斯卡指出的, BlockingQueue.take() 等待队列中有东西。

    排队,必要时等待 元素变为可用。

    如果你坚持要保持同步 consumer() BlockingQueue.poll(long timeout, TimeUnit unit) . 这将允许您创建优雅地处理空队列的逻辑。