Java synchronized method concurrent execution

I read this puzzle years ago (unfortunately I can’t find the reference) but didn’t appreciate it at the time. Java synchronized methods [1] can supposedly be invoked only by a single thread at a time. The essence of aforementioned puzzle was that, if the synchronized method obtains a lock on the object the method belongs to, then the method can be invoked from a different thread. The test below demonstrates this effect:

 

public class TestSynchronizedMethod {
  static class Worker implements Runnable{
  @Override
  public synchronized void run() {
    String name = Thread.currentThread().getName();
    System.out.println(name+" started run");
    synchronized(this){
      try {
            System.out.println(name+" waiting for mutex");
            this.wait();
            System.out.println(name+" done waiting for mutex");
          } catch (InterruptedException e) {
            System.out.println(name+" interrupted");
            e.printStackTrace();
          }
      }
   }
}

  public static void main(String...args) throws Exception{
    Worker worker = new Worker();
    Thread t1 = new Thread(worker, "Thread 1");
    Thread t2 = new Thread(worker, "Thread 2");
    System.out.println(t1.getName()+" starting");
    t1.start();
    System.out.println(t1.getName()+" started");
    System.out.println(t2.getName()+" starting");
    t2.start();
    System.out.println(t2.getName()+" started");
    t1.join();
    t2.join();
   }
}

The test produces an output similar to this:

Thread 1 starting
Thread 1 started
Thread 2 starting
Thread 1 started run
Thread 1 waiting for mutex
Thread 2 started
Thread 2 started run
Thread 2 waiting for mutex

If synchronized methods can’t be invoked by two threads at the same time, then the last two lines where the second thread enters the worker’s run method while it’s locked by the first thread shouldn’t be printed.

Be smart, don’t synchronize methods.

 

Resources

[1] Java synchronized methods
https://docs.oracle.com/javase/tutorial/essential/concurrency/syncmeth.html

4 thoughts on “Java synchronized method concurrent execution

  1. The “documentation” [1] is clear: “it is not possible for two invocations of synchronized methods on the same object to interleave”. The example has a single Worker instance with two threads trying to invoke the same synchronized method at the same time – this shouldn't be possible according to [1]. The wait() call clears any locks on the synchronized method (or disables whatever mechanism the JVM uses) and allows a different thread to enter the method while it is still executed by the first thread.

    As a simple experiment you can replace wait() with something else blocking, e.g. Thread.sleep(2000); you'll notice that the line “Thread 2 started run” isn't printed until 2 seconds have passed.

    [1] https://docs.oracle.com/javase/tutorial/essential/concurrency/syncmeth.html

    Like

  2. I see your point, it is just a matter of interpretation. The same paragraph you mention ends with “until the first thread is done with the object.” Calling wait() you declare explicitly you are done with the object.

    It is common knowledge that a synchronized method is shorthand to synchronized(this) full body *and* make it public API.

    Like

  3. > It is common knowledge that a synchronized method is shorthand to synchronized(this) full body *and* make it public API.
    Do you have a reference? I couldn't find anything about how the JVM implements method synchronization.

    Like

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s