views:

69

answers:

3

Hi,

With the following code, if a thread calls LoggingWidget.doSomething(), what is the order of lock acquisition that the thread has to go through? (i.e. does it get the Lock on LoggingWidget first, and then gets the lock on Widget ? )

public class Widget {
   public synchronized void doSomething() {

   }
}

public class LoggingWidget extends Widget {
    public synchronized void doSomething() {
         System.out.println(toString() + ": calling doSomething");
         super.doSomething();
    }
}
+2  A: 

The lock in this case is on this so there is only one lock, that being the instance. If there are more than one instance, each has an entirely separate lock regardless of whether it is a Widget or a LoggingWidget.

Let me put it another way. Your code is semantically equivalent to:

public class Widget {
  public void doSomething() {
    synchronized (this) {
      // do stuff
    }
  }
}

public class LoggingWidget extends Widget {
  public void doSomething() {
    synchronized (this) {
      System.out.println(toString() + ": calling doSomething");
      super.doSomething();
    }
  }
}

Only one of these methods is called so there's only one lock.

cletus
The last sentence is wrong IMHO. There is only one `this` in both `doSomething()` no matter if you have a LoggingWidget or a Widget.
Christopher Oezbek
Yes, if you call `System.identityHashCode( this )` in both methods, you will get the same value
David Soroko
+1  A: 

In Java, they're caleld monitors and are per object. In your example, there is only one monitor.

Michael Borgwardt
A: 

If you want to ensure you get the correct lock of type LoggingWidget and not Widget you can do this:

public class LoggingWidget extends Widget {
  private final Object readLock = new Object();

  public void doSomething() {
    synchronized (readLock) {
      System.out.println(toString() + ": calling doSomething");
      super.doSomething();
    }
  }
}

Or if you use Lombok you can just write

public class LoggingWidget extends Widget {
  @Synchronized("readLock")
  public void doSomething() {
    System.out.println(toString() + ": calling doSomething");
      super.doSomething();
  }
}
Shervin