简体   繁体   English

Java LinkedBlockingQueue实现

[英]Java LinkedBlockingQueue Realization

I looked at JDK LinkedBlockingQueue class and was lost. 我查看了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();
}

Look please at the last condition (c == 0) , I think it should be (c != 0) 请看最后一个条件(c == 0) ,我认为它应该是(c != 0)

Thank you, I understand. 谢谢,我明白了。 But I have another one question about LinkedBlockingQueue realization. 但我还有一个关于LinkedBlockingQueue实现的问题。 enqueue and dequeue function must not intersect. enqueue和dequeue函数不能相交。 I see that when put() is executed, take() could be executed too. 我看到执行put()时,也可以执行take()。 And head and tail objects have not synchronization, than enqueue and dequeue could work simultaneously in different thread. 并且head和tail对象没有同步,而enqueue和dequeue可以在不同的线程中同时工作。 It is not thread-safe, failures could occur. 它不是线程安全的,可能会发生故障。

No, the intent is to signal only when the queue goes from 0 to 1 (ie the first time something is added to an empty queue). 不,意图是在队列从0变为1时发出信号(即第一次将某些内容添加到空队列中)。 you don't need to "signal not empty" when adding items to a queue which already has items in it. 将项目添加到已包含项目的队列时,您不需要“发出非空信号”。 (You'll notice that the notEmpty condition is only waited on when the queue count == 0). (您会注意到只有在队列计数== 0时才会等待notEmpty条件)。

You don't need to signal on every put. 您不需要在每次放置时发出信号。 Ie, if the check was c != 0 then every time you put something you will be signaling that you aren't empty, but there is nobody to signal if you were not previously empty. 也就是说,如果支票是c != 0那么每次你放一些东西就会发出信号表明你不是空的,但是如果你之前没有空的话就没有人发出信号。 So c == 0 ensures that you only signal when the queue changes from an empty state to a non empty state. 所以c == 0确保当队列从空状态变为非空状态,你只有信号。

The comparison is c == 0, not c == 1, since the call to count is a "getAndIncrement" so 0 will be returned and then count will be incremented. 比较是c == 0,而不是c == 1,因为对count的调用是“getAndIncrement”,所以将返回0,然后count将递增。

Edit: Apparently someone already got to this before me :\\ 编辑:显然有人已经在我之前得到了这个:

c is a count before increment: ccount增量之前:

c = count.getAndIncrement();

So, this condition means "if queue was empty, notify others that now it's not empty". 因此,这种情况意味着“如果队列为空,请通知其他人现在它不是空的”。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM