4

I was asked this question in an interview.

Vector is already synchronized. Will it make any difference to call it inside a synchronized block?

       synchronized{
            // Call the vector here
       }

My answer is, there wouldn't be any difference, except for some loss in performance.

Is the answer correct?

Paŭlo Ebermann
  • 73,284
  • 20
  • 146
  • 210
Vinoth Kumar C M
  • 10,378
  • 28
  • 89
  • 130
  • What you showed is no valid Java syntax. A synchronized block always has an argument which specifies on what object's monitor to lock. – Paŭlo Ebermann Aug 14 '11 at 14:44

2 Answers2

12

No, it isn't completely correct. Vector is synchronized on the Vector instance itself, whereas the synchronized block actually synchronizes on the instance that holds the Vector. Two methods entering the synchronized block, must first acquire the monitor associated with this, and then acquire the monitor associated with the Vector instance.

An edge case is that if one of the threads, holds a monitor that the other requires (if you have other synchronized blocks as well), then you can have a deadlock.

Nevertheless, considering only the section of code posted, the thread that first acquires the monitor on this will be first to execute the operation on the Vector. Also, sequences of operations on the Vector instance can be performed by the first thread, without any interleaving of operations by the second thread; this is necessary if you want to perform an atomic sequence of operations on the Vector instance, which will not be the case on a plain synchronized Vector instance. To represent this in pseudocode, the sequence of operations in the two cases represented below will be different, if context-switching between two or more threads executing the same block occur:

Case A

synchronized
{
    vector.add(a);
    vector.add(b);
/*
 * a and b are always added to the vector in sequence.
 * If two threads execute this block, the vector will contain {a,b,a,b}.
 */
}

Case B

{
    vector.add(a);
    vector.add(b);

 /*
  * a and b need not be added to the vector in sequence.
  * If two threads execute this block, the vector will contain one of {a,b,a,b}, {a,a,b,b}....
  */
}
Vineet Reynolds
  • 76,006
  • 17
  • 150
  • 174
  • With all due respect, this is answering another question than the question asked in the OP. It errs on an extra issue (atomic sequence of operations) not mentioned in the original OP. – Jérôme Verstrynge Aug 11 '11 at 14:37
  • @JVerstry, no, it isn't. Java Concurrency in Practice documents this quite well; it is a classic example of synchronization failing for compound actions for synchronized collections. You can refer chapter 5 Section 1 of JCIP if you want to confirm your doubts. I cannot fathom how you can ignore the contents of the synchronized block in an answer. – Vineet Reynolds Aug 11 '11 at 14:49
  • @Vineet I do because I do not bring extra assumptions about the context of the question. – Jérôme Verstrynge Aug 11 '11 at 15:27
  • Actually, in Java the syntax `synchronized { ... }` is not allowed - one always has to specify on what to synchronize ([JLS 14.19](http://java.sun.com/docs/books/jls/third_edition/html/statements.html#14.19)). – Paŭlo Ebermann Aug 14 '11 at 14:43
  • @Paŭlo that's why I stated it is pseudocode, having noted that the posted snippet in the example is incomplete. I'm assuming that the question implies synchronizing on `this` and not any other object's monitor. – Vineet Reynolds Aug 14 '11 at 14:46
  • The thing is that it is important on which object one wants to lock. You answered as if it was `synchronized(this)`, but in fact it could be `synchronized(vector)` instead, which would give a quite different answer. – Paŭlo Ebermann Aug 14 '11 at 14:48
2

I would say that your answer is incorrect. The fact that Vector is synchronized only protects the internal state of the Vector. But most of the time, you need to make your class thread-safe.

Suppose you want to implement a container containing at most 10 elements, and you use Vector to store those elements. The add method will look like this:

public void add(Object item) {
    if (vector.size() == 10) {
        throw new TooManyItemsException();
    }
    else {
        vector.add(10);
    }
}

But this method is not thread-safe, and you have to make it synchronized to make it thread-safe. So yes, calling the vector method inside a synchronized block does make a difference.

The vector could also be part of a larger set of fields which must be updated in a synchronized way. In this case, even if the synchronized block only calls a method from the vector, it protects all the state of the object.

If you want a completely technical answer: it does make a difference because the synchronized block and the vector call do not synchronize on the same object, and thus don't do the same thing.

JB Nizet
  • 678,734
  • 91
  • 1,224
  • 1,255