Ben Flynn
Ben Flynn

Reputation: 18922

Does synchronizing on a thread safe object block other calls that might manipulate it?

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

Answers (3)

Gray
Gray

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

yshavit
yshavit

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

Tudor
Tudor

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

Related Questions