Synchronized method calls itself recursively. Is this broken?

Thom picture Thom · Nov 2, 2012 · Viewed 12.6k times · Source

The point of this question is to illustrate that Java is not working as I expected.

How would you expect the following code to behave?

public class SynchTester {
  private static SynchTester synchTester;

  public synchronized static SynchTester getSynchTester(){
    if(synchTester==null){
      synchTester = new SynchTester();
    }

    return synchTester;
  }

  private SynchTester() {
    SynchTester myTester = getSynchTester();
  }

  public static void main(String[] args) {
    SynchTester tester = SynchTester.getSynchTester();
  }
}

I would expect it to hang with a deadlock waiting on the recursion to complete, but instead it throws StackOverflow. Evidently synchronized does not block access to the same thread.

Is this a bug?

Answer

Duncan Jones picture Duncan Jones · Nov 2, 2012

In Java, synchronized locks are reentrant.

Recall that a thread cannot acquire a lock owned by another thread. But a thread can acquire a lock that it already owns. Allowing a thread to acquire the same lock more than once enables reentrant synchronization. This describes a situation where synchronized code, directly or indirectly, invokes a method that also contains synchronized code, and both sets of code use the same lock. Without reentrant synchronization, synchronized code would have to take many additional precautions to avoid having a thread cause itself to block.

Source: see bottom of this page