Quoting the documentation:
"BlockingQueue implementations are thread-safe. All queuing methods achieve their effects atomically using internal locks or other forms of concurrency control. However, the bulk Collection operations addAll, containsAll, retainAll and removeAll are not necessarily performed atomically unless specified otherwise in an implementation. So it is possible, for example, for addAll(c) to fail (throwing an exception) after adding only some of the elements in c."
Since there isn't written anything in particular in the description of the LinkedBlockingQueue.addAll()
operation, I have to assume that's not thread safe.
Do you agree with me that the only solution in order to guarantee that all the elements added through an addAll() are contiguous (i.e. added together) is to use a Lock
everytime that the queue is modified (with an add
or take
operation)? For example:
BlockingQueue<T> queue = new LinkedBlockingQueue<>();
Lock lock = new ReentrantLock();
//somewhere, some thread...
lock.lock();
queue.addAll(someCollection);
lock.unlock();
//somewhere else, (maybe) some other thread...
lock.lock();
queue.take();
lock.unlock();
IMPORTANTE UPDATE:
Wow nobody saw a big bug in the previous example: since the take()
is a blocking operation, and since the lock is needed in order to add element to the queue, as soon as the queue will be empty the program will enter in a deadlock state: a writer cannot write since the lock is possessed by the take()
, and at the same time the take()
will be in a blocked state until something is written in the queue (which it can't happen for the previous reason). Any idea? I think that the most obvious one is remove the lock around the take()
but then maybe the desired atomicity of addAll()
is not guaranteed.