Java LinkedBlockingQueue源代码混乱

时间:2014-11-06 05:26:34

标签: java blockingqueue

我正在阅读Java LinkedBlockingQueue源代码,我对put operation有两个问题。

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();
    } finally {
        putLock.unlock();
    }
    if (c == 0)
        signalNotEmpty();
}

我不明白:

  1. 检查c + 1 < capacity时是否notFull.signal()。为什么不使用c < capacity
  2. 为什么在功能结束时signalNotEmpty时会发出c == 0
  3. 此外,我也不明白为什么头/尾必须是transient

1 个答案:

答案 0 :(得分:4)

你的两个问题的答案:

  1. c + 1 < capacity检查之前,有c = count.getAndIncrement();的来电。由于计数在之后被提取并被分配到c,因此c与<{1}}之间存在 1 的差异。实际计数,因此检查中为+ 1
  2. 当队列从空转变为非空时,只需要发送非空信号。仅当第一个元素添加到空(0个元素)队列时才会出现这种情况。至于c此时 0 而不是 1 ,请参阅第一个问题的答案。
  3. 关于headtail transient:他们不需要在对象序列化时保留,因为他们通过对象的默认构造函数初始化反序列化。