Reputation: 1109
Let's take a thread safe class like LinkedBlockingDeque
:
BlockingQueue<Task> taskQueue = new LinkedBlockingDeque<Task>();
I know that operations like take
and put
are thread safe, so they respect the happened-before relationship.
But what if I want to compose some operations to make them atomic? Like this:
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
If it was a not thread safe class, I could do something like this:
synchronized(taskQueue) {
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
}
But it is not that simple, I do not think that the implementations of take
and put
use the object lock.
How do you handle this scanario?
Upvotes: 1
Views: 211
Reputation: 719709
How do you handle this scenario?
In general, you cannot "compose" operations on the concurrent data structures without using external locking of some kind. And when you do that, you reintroduce the concurrency bottleneck that you were trying to avoid by using the concurrent data structure.
In this case, you are correct. The LinkedBlockingDeque
class uses a private lock object for synchronization, etcetera.
Upvotes: 3