Is drainTo of LinkedBlockingQueue safe? I followed the source

Overview

I decided to use drainTo because I had to get the status of the temporary point from LinkedBlockingQueue in my business.

drainTo is

Removes all available elements from this queue and adds them to the specified collection.

It is a method called.

However, if you look at the help,

The behavior of this operation is undefined if the specified collection is modified while the operation is in progress.

Publisher

There was an uneasy sentence, and I investigated whether there was a problem.

2017/11/30 postscript

Source

LinkedBlockingQueue.java


/**
* @throws UnsupportedOperationException {@inheritDoc}
* @throws ClassCastException            {@inheritDoc}
* @throws NullPointerException          {@inheritDoc}
* @throws IllegalArgumentException      {@inheritDoc}
*/
public int drainTo(Collection<? super E> c, int maxElements) {
    if (c == null)
        throw new NullPointerException();
    if (c == this)
        throw new IllegalArgumentException();
    if (maxElements <= 0)
        return 0;
    boolean signalNotFull = false;
    final ReentrantLock takeLock = this.takeLock;
    takeLock.lock();
    try {
        int n = Math.min(maxElements, count.get());
        // count.get provides visibility to first n Nodes
        Node<E> h = head;
        int i = 0;
        try {
            while (i < n) {
                Node<E> p = h.next;
                c.add(p.item);
                p.item = null;
                h.next = h;
                h = p;
                ++i;
            }
            return n;
        } finally {
            // Restore invariants even if c.add() threw
            if (i > 0) {
                // assert h.item == null;
                head = h;
                signalNotFull = (count.getAndAdd(-i) == capacity);
            }
        }
    } finally {
        takeLock.unlock();
        if (signalNotFull)
            signalNotFull();
    }
}

In addition, what is actually used is drainTo with one argument,

LinkedBlockingQueue.java


return drainTo(c, Integer.MAX_VALUE);

And, since it is just calling the same method that is overloaded, there is no problem if you check here.

variable

takeLock A lock object for locking the ** retrieval ** of data.

putLock Although it does not appear in the above source, it is a lock object for locking the ** addition ** of data.

count ʻAtomicIntegertype field. Every time I change the data, it seems that I change it manually in the class. (It seems that it is not just returningQueue.size`)

Commentary

We will look at only the necessary parts in order from the top.

final ReentrantLock takeLock = this.takeLock;
takeLock.lock();

Acquire the acquisition lock before starting the data acquisition.

int n = Math.min(maxElements, count.get());

Before starting data acquisition, ** decide how many items to acquire from the beginning **. This allows you to ** ignore data added during the process of drainTo **.

Conclusion

It seems that it can be said.

Digression (impression)

personally,

** If you want to get data all at once, you should lock the additions in the meantime! ** **

I will think.

I was wondering if there was an approach of "deciding the number of data first". It was a very good study.

Recommended Posts

Is drainTo of LinkedBlockingQueue safe? I followed the source
I read the source of ArrayList I read
I read the source of Integer
I read the source of Long
I read the source of Short
I read the source of Byte
I read the source of String
05. I tried to stub the source of Spring Boot
'% 02d' What is the percentage of% 2?
[Reference example] Copyright is described in the comment of the source code.
What is testing? ・ About the importance of testing
I investigated the internal processing of Retrofit
[day: 5] I summarized the basics of Java
[Swift] Get the height of Safe Area
What is the data structure of ActionText?
What is JSP? ~ Let's know the basics of JSP !! ~
I want to output the day of the week
ActiveSupport underscore is not the inverse of camelize
I checked the place of concern of java.net.URL # getPath
The order of Java method modifiers is fixed
I understood the very basics of character input
I compared the characteristics of Java and .NET
I want to var_dump the contents of the intent
I touched on the new features of Java 15
The official name of Spring MVC is Spring Web MVC
I tried using the profiler of IntelliJ IDEA
I checked the number of taxis with Ruby
Try the free version of Progate [Java I]
The handling of Java Future is too dull, so I will try various ideas.