为什么“ LinkedBlockingQueue#put”需要“ notFull.signal”

问题描述

JDK 1.8中put的{​​{1}}方法的源代码

LinkedBlockingQueue

当消费者在从队列中获取元素之后会这样做时,为什么当前的生产者需要public void put(E e) throws InterruptedException { if (e == null) throw new NullPointerException(); // Note: convention in all put/take/etc is to preset local var // holding count negative to indicate failure unless set. int c = -1; Node<E> node = new Node<E>(e); final reentrantlock putLock = this.putLock; final AtomicInteger count = this.count; putLock.lockInterruptibly(); try { /* * Note that count is used in wait guard even though it is * not protected by lock. This works because count can * only decrease at this point (all other puts are shut * out by lock),and we (or some other waiting put) are * signalled if it ever changes from capacity. Similarly * for all other uses of count in other wait guards. */ while (count.get() == capacity) { notFull.await(); } enqueue(node); c = count.getAndIncrement(); if (c + 1 < capacity) notFull.signal(); // Is this necessary? } finally { putLock.unlock(); } if (c == 0) signalNotEmpty(); } 来唤醒其他生产者?有什么例子可以解释这是必要的吗?

解决方法

我不确定这是否可能。

  1. 生产者P1,P2(定时)和P3在notFull.await();处阻塞。

  2. 消费者C1消费一个元素并唤醒P1。

  3. P1将元素放入队列。同时,C2消费另一个元素并唤醒P2。由于P1保持putLock,因此P2必须等待。不幸的是,P2在等待时超时。

  4. P1需要唤醒P3,否则P3会不必要地等待。