首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >LinkedBlockingQueue的放置和功能实现

LinkedBlockingQueue的放置和功能实现
EN

Stack Overflow用户
提问于 2018-04-20 11:34:44
回答 1查看 95关注 0票数 2

我正在进行LinkedBlockingQueue put( e )和函数的内部实现。

代码语言:javascript
复制
public E take() throws InterruptedException {
    E x;
    int c = -1;
    final AtomicInteger count = this.count;
    final ReentrantLock takeLock = this.takeLock;
    takeLock.lockInterruptibly();
    try {
        while (count.get() == 0) {
            notEmpty.await();
        }
        x = dequeue();
        c = count.getAndDecrement();
        if (c > 1)
            **notEmpty.signal();**
    } finally {
        takeLock.unlock();
    }
    if (c == capacity)
        signalNotFull();
    return x;
}

  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();
    }

在这两种方法中,在与容量进行比较之后,都没有得到在条件下调用signal()的原因。如果有人能解释的话,会非常感激的。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2018-04-20 14:02:01

下面是我可以考虑使用的一种情况:

代码语言:javascript
复制
if (c > 1)
    notEmpty.signal();

假设队列是空的,并且有3个线程,thread_1、thread_2、thread_3。

  • thread_1打电话给take(),在notEmpty.await()被堵住。
  • thread_2打电话给take(),在notEmpty.await()被堵住。
  • thread_3打电话给take(),在notEmpty.await()被堵住。

然后,出现了另外3个线程,thread_4、thread_5、thread_6。

  • thread_4调用put(),在队列中添加一个元素,以及signal thread_1。
  • thread_1醒来,重新创建takeLock,并尝试使用第一个元素。
  • 同时,thread_5调用put(),在队列中添加另一个元素,并添加signal thread_2。
  • thread_2醒醒,试着重新设置takeLock,但是thread_1现在持有锁,所以它必须等待。
  • thread_6中断thread_2,thread_2抛出InterruptedException并终止。
  • thread_1接受第一个元素。但是,这个队列中还有另一个元素,所以上面代码中的c > 1 就出现了。如果signal**,thread_1不调用,则thread_3无法唤醒并接受第二个元素。
  • thread_1调用signal,thread_3醒来,并接受第二个元素。
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/49940745

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档