4

If I have the following code

class SomeClass {    
...
public synchronized methodA() {
....
}

public synchronized methodB(){
....
}
}

This would synchronized on the 'this' object.
However, if my main objective here is to make sure multiple threads don't use methodA (or methodB) at the same time, but they CAN use methodA AND methodB concurrently,
then is this kind of design restrictive? since here thread1 lock the object (monitor object associated with the object) for running methodA but meanwhile thread2 is also waiting on the object lock even though methodA and methodB can run concurrently.
Is this understanding correct?

If yes, is this the kind of situation where we use synchronized block on a private dummy object so that methodA and methodB can run parallely with different thread but not methodA (or methodB) with different threads.
Thanks.

Ankur
  • 11,239
  • 22
  • 63
  • 66
  • Answered here: http://stackoverflow.com/questions/574240/synchronized-block-vs-synchronized-method - please use the search function, the other question even has exactly the same name and covers the same problem. – Andreas Dolk May 27 '11 at 09:59
  • I think you're right, but one gotcha is that lock for a static method is different to the lock for a normal object method. The documentation is pretty good for this stuff: http://download.oracle.com/javase/tutorial/essential/concurrency/syncmeth.html – Adrian Mouat May 27 '11 at 10:01

3 Answers3

9

You've answered the question yourself: use one lock object per method and you're safe.

private final Object lockA = new Object();
private final Object lockB = new Object();
public void methodA() {
    synchronized(lockA){
        ....
    }
}
public void methodB() {
    synchronized(lockB){
        ....
    }
}

For more advanced locking mechanisms (e.g. ReentrantLock), read Java Concurrency in Practice by Brian Goetz et al. You should also read Effective Java by Josh Bloch, it also contains some items about using synchronized.

Sean Patrick Floyd
  • 292,901
  • 67
  • 465
  • 588
2

If you want to allow running methodA() and methodB() concurrently but otherwise restrict each method to one thread then you need two separate objects to synchronize on. For instance:

class SomeClass {
    private final Object lockA = new Object();
    private final Object lockB = new Object();

    public void methodA() {
        synchronized (lockA) {
            // 
        }
    }

    public void methodB() {
        synchronized (lockB) {
            // 
        }
    }
}
WhiteFang34
  • 70,765
  • 18
  • 106
  • 111
1

If my understanding is correct you want to allow thread T1 to run methodA() at the same time thread T2 runs methodB() -- but you don't want thread T1 to run methodA() at the same time thread T2 runs methodA() (and same for methodB) right? For this scenario you can't use just a simple synchronized method -- instead, as you said, you will need 2 dummy objects (one for methodA and one for methodB) to synchronize on. Or you could use the new Lock class -- one Lock instance per method.

Liv
  • 6,006
  • 1
  • 22
  • 29
  • Then you can use one of the methods shown above or as I said have a look at java.util.concurrent.locks.ReentrantLock for instance. – Liv May 27 '11 at 10:27