为什么 "LinkedBlockingQueue#put" 需要 "notFull.signal()"
Why does "LinkedBlockingQueue#put" need "notFull.signal()"
LinkedBlockingQueue
in JDK 1.8的put
方法源码:
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();
}
为什么当前生产者需要在 notFull.signal()
之前唤醒其他生产者,而消费者在从队列中取出元素后会这样做?有什么例子可以说明这是必要的吗?
我不确定这是否可行。
生产者 P1、P2(定时)和 P3 在 notFull.await();
阻塞。
消费者C1消费一个元素并唤醒P1。
P1 将把元素放入队列中。与此同时,C2 消耗另一个元素并唤醒 P2。由于 P1 持有 putLock
,P2 必须等待。不幸的是,P2 在等待时超时。
P1需要唤醒P3,否则P3会无谓地等待
LinkedBlockingQueue
in JDK 1.8的put
方法源码:
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();
}
为什么当前生产者需要在 notFull.signal()
之前唤醒其他生产者,而消费者在从队列中取出元素后会这样做?有什么例子可以说明这是必要的吗?
我不确定这是否可行。
生产者 P1、P2(定时)和 P3 在
notFull.await();
阻塞。消费者C1消费一个元素并唤醒P1。
P1 将把元素放入队列中。与此同时,C2 消耗另一个元素并唤醒 P2。由于 P1 持有
putLock
,P2 必须等待。不幸的是,P2 在等待时超时。P1需要唤醒P3,否则P3会无谓地等待