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();
// #Question 1
if (c + 1 < capacity)
notFull.signal();
} finally {
putLock.unlock();
}
if (c == 0)
signalNotEmpty();
}
我有两个问题:
<#1> #Question 1在什么条件下可以开心?为什么我们在将一个对象放入队列之后在put方法中调用notFull.signal()。2为什么signalNotEmpty应该在notEmpty.signal()之前锁定takeLock
private void signalNotEmpty() {
final ReentrantLock takeLock = this.takeLock;
takeLock.lock();
try {
notEmpty.signal();
} finally {
takeLock.unlock();
}
}
答案 0 :(得分:1)
1)如果队列已满,则条件为true
。如果我理解正确,notFull.signal()
调用在LinkedBlockingQueue
的当前实现中并不是必需的。由于所有锁和条件都是私有的,派生类也不会受益于调用。所以我想这只是确保未来课堂扩展的正确性。
2)在发出takeLock
信号时,需要获取notEmpty
以防止其他线程清空队列。