Java LinkedBlockingQueue 实现

3

我看了一下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可以同时工作。这不是线程安全的,可能会导致故障。

关于编辑:您可能错过了while (count.get() == 0) notEmpty.await();在take中。 - bestsss
1
如果您有新问题,请提出一个新问题 --- 当现有问题只是被更改时,这真的很令人困惑。 - Kevin Bourrillion
3个回答

3

不,意图是只在队列从0到1时发出信号,即第一次向空队列添加内容时。在向已经有项目的队列添加项目时,您不需要“发出非空信号”。(您会注意到,只有在队列计数== 0时才等待notEmpty条件)。


1

你不需要在每次放置时发出信号。也就是说,如果检查是 c != 0,那么每次放置东西时,你都会发出信号表明你不是空的,但如果之前你不是空的,那么没有人可以发出信号。因此,c == 0 确保只有在队列从空状态变为非空状态时才发出信号。

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

编辑:显然有人在我之前已经处理了这个问题 :\


0

c 是在增加之前的 count

c = count.getAndIncrement();

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


c = count.getAndIncrement(); 如果队列为空,那么 c 的值为 1,而不是 0。 - itun
@itun - 不是的,“getAndIncrement”意味着“获取当前值(以返回值形式)并增加存储的值”。 因此,当队列为空时,c == 0。 - jtahlborn

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接