Java LinkedBlockingQueue实现

时间:2011-03-29 20:07:37

标签: java collections

我查看了JDK 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;
    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(e);
        c = count.getAndIncrement();
        if (c + 1 < capacity)
            notFull.signal();
    } finally {
        putLock.unlock();
    }
    if (c == 0)
        signalNotEmpty();
}

请注意最后一个条件(c == 0),我认为它应该是(c != 0)

谢谢,我明白了。 但我还有一个关于LinkedBlockingQueue实现的问题。 enqueue和dequeue函数不能相交。我看到执行put()时,也可以执行take()。并且head和tail对象没有同步,而enqueue和dequeue可以在不同的线程中同时工作。它不是线程安全的,可能会发生故障。

3 个答案:

答案 0 :(得分:3)

不,当队列从0变为1时(即第一次将某些内容添加到空队列中),目的是仅发送 。将项目添加到已包含项目的队列时,您不需要“发出非空信号”。 (您会注意到只有当队列计数== 0时才会等待notEmpty条件。)

答案 1 :(得分:1)

您不需要每次发出信号。即,如果支票是c != 0,那么每次你放一些东西,你都会发出信号表明你不是空的,但是如果你之前没有空的话就没有人发出信号。因此c == 0确保您仅在队列从空状态更改到非空状态时发出信号。

比较是c == 0,而不是c == 1,因为对count的调用是“getAndIncrement”,所以将返回0,然后count将递增。

编辑:显然有人已经在我面前这样做了:\

答案 2 :(得分:0)

增量之前

ccount

c = count.getAndIncrement();

所以,这个条件意味着“如果队列为空,请通知其他人现在它不是空的”。