views:

426

answers:

6
class A {
    public synchronized void myOneMethod() {
        // ...
    }
}

class B extends A {
    public synchronized void myOtherMethod() {
        // ...
    }
}

// ...

B myObject;

// ...

myObject.myOneMethod(); // acquires lock
myObject.myOtherMethod(); // same lock?

How I understand the synchronization model, I'd say that yes, it does, because the lock / monitor is associated with the instance myObject, and it doesn't matter where the method was defined. But am I right? If not, why? If yes, why are you sure, and I'm not? :-)

+5  A: 

Yes, synchronized is equivalent to synchronized(this).

To be more precise:

For a class (static) method, the lock associated with the Class object for the method's class is used. For an instance method, the lock associated with this (the object for which the method was invoked) is used.

pgras
For instance methods, yes.
Jon Skeet
+7  A: 

Yes, you are right, and you got the explanation right too. Nothing much to add.

Note that if the methods were static, then they would synchronize on different objects, namely their respective classes (A and B).

EDIT: Why am I sure? I don't know, why are you not sure? ;-) myObject is just one object - there isn't any distinction between the myObject attributes that come from class A and those that come from class B. (Well, technically you could probably use reflection to find out which are which, so there must be some distinction, but forget about reflection for now. For common operations on the object there's no distinction.)

David Zaslavsky
+1  A: 

Yes. Java uses "monitors" to implement synchronization, and synchronized methods use the object instance they're called on as monitor, which is obviously the same in this case.

Note that this is NOT true for static methods! There, the class instance of (I think) the declaring class is used, which would not be the same one.

Michael Borgwardt
A: 

Yes you are correct

When one thread is executing a synchronized method for an object, all other threads that invoke synchronized methods for the same object block (suspend execution) until the first thread is done with the object. In this case the object is B

Paul Whelan
+1  A: 

If you want to be more explicit about your locking, you could do something like this:

class A {

    protected final Object  mutex = new Object();
    public void myOneMethod() {
        synchronized (mutex) {
            // ...
        }
    }
}

class B extends A {
    public  void myOtherMethod() {
        synchronized (mutex) {
            // ...
        }
    }
}

In fact, this pattern is recommended by Brian Goetz in Java Concurrency in Practice, section 4.2.1 "The Java monitor pattern". That way you know exactly where your monitor is coming from.

Julien Chastang
Yup. Also, this is what Jon Skeet does: http://stackoverflow.com/questions/609963/java-what-if-anything-is-locked-by-synchronized-methods-apart-from-the-object/609981#609981 ;) I'll use that pattern, except for those methods where it actually makes most sense to lock on "this".
Hanno Fietz
A: 

Just a small addition for people who might be interested in the future..

Additionally remember that locks in Java are reentrant. If they were not this code of yours would result in a deadlock since as you've indicated both operations require the same lock.

Selim