concurrentLinkedQueue offer / poll blocking

时间:2014-04-14 09:34:24

标签: java multithreading

确实提供了块调查,反之亦然?意思是,生产者可以提供并同时消费者试图进行民意调查吗?或者如果一个制作人提供,队列会阻塞直到他完成?

对象A

  while (true){
    inputQueue.offer(newPartList);
}

对象B

     while (true){
    inputQueue.poll(newPartList);
}

3 个答案:

答案 0 :(得分:6)

不,它没有。请改用LinkedBlockingDeque。请记住使用BlockingDequeueBlockingQueue接口中的方法来获取值。因为这些方法被实现为阻止。

<强>更新

offerpoll方法都没有阻止。在链接接口中,只有put*take*方法被实现为阻塞。只要队列已满,put就会阻塞,take会阻塞队列为空。

现在我看到你在问别的什么。 在LinkedBlockingDeque调用offerpoll,因为此实现具有用于同步访问的inernal Lock。在ConcurrentLinkedQueue's JavaDoc中明确声明:

This implementation employs an efficient "wait-free" algorithm based on one described in Simple, Fast, and Practical Non-Blocking and Blocking Concurrent Queue Algorithms by Maged M. Michael and Michael L. Scott.

表明这些操作不会相互阻挡。如果您有兴趣,我强烈建议阅读该论文以获得更多见解。

答案 1 :(得分:3)

当您说“对象A / B”时,假设您的意思是“线程A / B”。

poll()和offer()都不是阻塞方法(阅读Queue接口的文档)。

我不理解你的示例中的while(true)循环,但是你似乎在询问当你有一个空队列时会发生什么,以及在线程A之间的数据竞争调用q.offer()和调用q.poll()。

的线程B.

由于您询问的是ConcurrentLinkedQueue,答案很简单:ConcurrentLinkedQueue本质上是线程安全的,这意味着只有两种可能的结果。线程A赢得比赛(即,offer()“发生在”poll()之前),或者线程B赢得比赛(poll()“发生在”offer()之前)。

There is no such thing as "at the same time."  In the case of ConcurrentLinkedQueue,
"thread safe" means that no matter how close the race, there will always be a winner
and a loser. 

因此,如果A获胜(offer()发生在poll()之前),则线程B将从队列中获取数据,并且队列将保留为空。如果B获胜(poll()发生在offer()之前),则线程B将变为null(再次,读取Queue接口的doc),并且数据将保留在队列中。

答案 2 :(得分:2)

它并不像看起来那么简单。实际上根据ConcurrentLinkedQueue的javadoc,它遵循非阻塞算法:

  

“此实现采用了一种有效的非阻塞算法,该算法基于Maged M. Michael和Michael L. Scott在简单,快速,实用的非阻塞和阻塞并发队列算法中所描述的算法。”

如果您有足够的好奇并查看源代码,您会看到类似的内容:

/**
 * Inserts the specified element at the tail of this queue.
 * As the queue is unbounded, this method will never return {@code false}.
 *
 * @return {@code true} (as specified by {@link Queue#offer})
 * @throws NullPointerException if the specified element is null
 */
public boolean offer(E e) {
    checkNotNull(e);
    final Node<E> newNode = new Node<E>(e);

    for (Node<E> t = tail, p = t;;) {
        Node<E> q = p.next;
        if (q == null) {
            // p is last node
            if (p.casNext(null, newNode)) {
                // Successful CAS is the linearization point
                // for e to become an element of this queue,
                // and for newNode to become "live".
                if (p != t) // hop two nodes at a time
                    casTail(t, newNode);  // Failure is OK.
                return true;
            }
            // Lost CAS race to another thread; re-read next
        }
        else if (p == q)
            // We have fallen off list.  If tail is unchanged, it
            // will also be off-list, in which case we need to
            // jump to head, from which all live nodes are always
            // reachable.  Else the new tail is a better bet.
            p = (t != (t = tail)) ? t : head;
        else
            // Check for tail updates after two hops.
            p = (p != t && t != (t = tail)) ? t : q;
    }
}

源代码中的注释表明了一种相当于尝试错误的方法,而不是安全同步方式。