Reputation: 18922
Suppose I create a thread safe object:
PriorityBlockingQueue<Object> safeQueue = new PriorityBlockingQueue<Object>();
If I synchronize on it:
synchronized (safeQueue) {
....
}
Does code that block:
// some non-synchronized block
Object value = safeQueue.poll();
Upvotes: 3
Views: 597
Reputation: 116878
No. The only time you get any blocking is if another thread is also doing a synchronized
on the same object. If your code is synchronized (safeQueue)
then a call to PriorityBlockingQueue.poll()
would only block if poll()
was a synchronized
method or if the code used synchronized (this)
code.
When you call safeQueue.poll()
the PriorityBlockingQueue
code is actually using an internal ReentrantLock
, and not doing a synchronized (this)
. Here's the code for poll()
:
public E poll() {
final ReentrantLock lock = this.lock;
lock.lock();
try {
return q.poll();
} finally {
lock.unlock();
}
}
Lastly, as you mention, PriorityBlockingQueue
is already reentrant so you do not need to synchronize on it to allow multiple threads to access the queue. You could still need to synchronize on it if you needed to solve race conditions in your own code of course.
Upvotes: 4
Reputation: 43391
The short answer is: it depends on where the thread-safe class's thread safety comes from.
You have to depend on the class's documentation, or its implementation code if you want to go down that route (beware of changes in future versions...), or be defensive and not trust it, instead synchronizing on another object for your atomicity needs (or whatever else you're synchronizing for).
It certainly doesn't have to block, especially as many of the java.util.concurrent
classes are non-blocking (and thus don't synchronize on themselves to achieve thread safety). On the other hand, if the class gets its thread safety from synchronized(this)
(or, equivalently, synchronized
instance methods), then yes, that'll block. An example of this is the map returned from Collections.synchronizedMap
, in which that blocking is documented and is actually an intended feature (so that you can atomically query and modify the map).
Upvotes: 2
Reputation: 62439
It is possible if the object itself has methods that are synchronized on the instance. For example:
MyClass c = new MyClass();
synchronized(c) {
...
}
and MyClass
is:
class MyClass {
// foo needs a lock on this
public synchronized void foo() {
...
}
}
Now, a call to c.foo();
outside of a synchronized
section will still block if it's executed in parallel with the code written above.
For example, the old Java Vector
class was synchronized internally like this, so locking on the object from the outside could interfere with the internal locking.
Upvotes: 0