Synchronized method calls itself recursively. Is this broken?

13,920

Solution 1

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

Solution 2

A synchronized method needs to be able to get a lock on the monitor object. The monitor object is the instance (or class for a static method). A thread that already has the lock does not need to get it again. So yes, that could cause a stackoverflow (harhar).

Solution 3

from the java tutorials:

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.

So I think the syncronized keyword worked as expected, and a synchronized recursive call is perfectly legal (and working) in java.

Share:
13,920
Thom
Author by

Thom

Seasoned software architect building mobile word games for himself. Background in web services and Spring Framework.

Updated on June 05, 2022

Comments

  • Thom
    Thom almost 2 years

    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?

  • Thom
    Thom over 11 years
    That's kinda what I was thinking. Cite your source, please?
  • akaIDIOT
    akaIDIOT over 11 years
    @Thom Personal experience, mostly, but also docs.oracle.com/javase/tutorial/essential/concurrency/…
  • Jack
    Jack almost 4 years