关于LinkedBlockingQueue源代码的一些困惑

时间:2018-03-29 13:53:45

标签: java java-8

在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();
        // #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();
            }
        }

1 个答案:

答案 0 :(得分:1)

1)如果队列已满,则条件为true。如果我理解正确,notFull.signal()调用在LinkedBlockingQueue的当前实现中并不是必需的。由于所有锁和条件都是私有的,派生类也不会受益于调用。所以我想这只是确保未来课堂扩展的正确性。

2)在发出takeLock信号时,需要获取notEmpty以防止其他线程清空队列。