Java LinkedBlockingQueue Реализация - PullRequest
3 голосов
/ 30 марта 2011

Я посмотрел на класс 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 ]

3 голосов
/ 30 марта 2011

Нет, цель состоит в том, чтобы сигнализировать только , когда очередь переходит от 0 до 1 (то есть при первом добавлении чего-либо в пустую очередь).вам не нужно «сигнализировать не пусто» при добавлении элементов в очередь, в которой уже есть элементы.(Вы заметите, что условие notEmpty ожидается только тогда, когда число очередей == 0).

1 голос
/ 30 марта 2011

Вам не нужно сигнализировать о каждом путе. То есть, если проверка была c != 0, то каждый раз, когда вы кладете что-то, вы будете сигнализировать, что вы не пусты, но никто не будет сигнализировать, если вы ранее не были пустыми. Таким образом, c == 0 гарантирует, что вы подаете сигнал только тогда, когда очередь меняет с пустого состояния на непустое состояние.

Сравнение c == 0, а не c == 1, так как вызов count является "getAndIncrement", поэтому возвращается 0, а затем увеличивается счетчик.

Редактировать: Видимо, кто-то уже до меня дошел: \

0 голосов
/ 30 марта 2011

c - это count до приращения:

c = count.getAndIncrement();

Итак, это условие означает «если очередь пуста, сообщите другим, что теперь она не пуста».

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...