Is synchronization enough to make the drainTo () method of the BlockingQueue atom?

If I just do something like this:

synchronized(taskQueue) { //taskQueue is a BlockingQueue 
  taskQueue.drainTo(tasks); //tasks is a list
}

      

I'm sure there are concurrent calls taskQueue.put()

and taskQueue.take()

cannot be executed inside a synchronized block?

In other words, am I making drainTo () atomic?

Or, more generally, how to create a set of thread-safe atomic operations?

Example:

if(taskQueue.size() == 1) {
   /*Do a lot of things here, but I do not want other threads
     to change the size of the queue here with take or put*/
}
//taskQueue.size() must still be equal to 1

      

+3


source to share


2 answers


See below excerpt from BlockingQueue Java docs

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 the implementation specifies otherwise. So it is possible, for example, for addAll (c) to give up (throwing an exception) after only adding some elements from c.

Also, check out an example that shows that the BlockingQueue implementation can be safely used with multiple producers and multiple consumers.



So, if you are not using bulk collection operations such as addAll, containsAll, retainAll and removeAll

then you are thread safe.

You do not even need to synchronized(taskQueue) {

, and can be used directly taskQueue.drainTo(tasks);

, because the implementation BlockingQueue are thread-safe operations with mass gatherings, such as put

, take

, drainTo

, etc.

Hope this helps!

+3


source


Take LinkedBlockingQueue as an example, it has "takeLock" and "putLock" which are its member variables.

So a dose of client-side synchronization doesn't help here, as other "accept" actions are not protected by this lock, even if that lock comes from the queue itself.



DrainTo () is protected by "takeLock", it is thread-protected for any other take operation. But for put operations they are protected by putLock, so this will not be affected.

So I guess nothing is needed here!

+3


source







All Articles