concurrentLinkedQueue offer/poll blocking

回眸只為那壹抹淺笑 提交于 2020-05-13 07:51:26

问题


does offer blocks poll or vice versa ? meaning , can a producer offer and at the same time a consumer trying to poll ? or if a producer was offering , the queue blocks till he is done ?

object A

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

object B

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

回答1:


No, it does not. use LinkedBlockingDeque instead. Remember to use methods from BlockingDequeue or BlockingQueue interfaces to get values. as these methods are implemented as blocking.

Update

Neither offer nor poll methods are blocking. In linked interfaces only put* and take* methods are implemented as blocking. put blocks as long as the queue is full, take blocks if the queue is empty.

Now I see You are asking something else. In LinkedBlockingDeque calling offer blocks poll, because this implementation has inernal Lock for synchronizing access. In ConcurrentLinkedQueue's JavaDoc it is explicitly stated, that:

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

which suggests that these operations don't block each other. If You are interested, I strongly suggest reading that paper for more insight.




回答2:


Assuming you mean "thread A/B" when you say "object A/B".

Neither poll() nor offer() is a blocking method (Read the documentation for the Queue interface).

I don't understand the while(true) loops in your example, but you appear to be asking what happens when you have an empty queue, and a data race between thread A, which calls q.offer(), and thread B, which calls q.poll().

Since you are asking about a ConcurrentLinkedQueue, the answer is simple: ConcurrentLinkedQueue is inherently thread-safe, which means there can be only two possible outcomes. Either thread A wins the race (i.e., the offer() "happens before" the poll()), or thread B wins the race (the poll() "happens before" the 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. 

So, if A wins (the offer() happens before the poll()), then thread B will get the datum from the queue, and the queue will be left empty. If B wins (the poll() happens before the offer()), then thread B will get null (Again, read the doc for the Queue interface), and the datum will be left sitting in the queue.




回答3:


It is not as simple as it seems to be. Actually acording to ConcurrentLinkedQueue's javadoc, it follows a non-blocking algorithm:

"This implementation employs an efficient non-blocking 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."

If you are curious enough and have a look at the source code, you'll see something like this:

/**
 * 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;
    }
}

The comments from the source code suggest a rather try-error aproach than a secured-synchronized one.



来源:https://stackoverflow.com/questions/23056659/concurrentlinkedqueue-offer-poll-blocking

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!