Can two threads access a synchronized method at the same time?

So can two threads access a synchronized method at the same time?

Yes and no:

  • Yes, if the method is called on different instances of the class.

  • No, two threads can't simultaneously call synchronized methods on the same instance of the class. This is the case even if the two threads call different methods (as long as the instance is the same).


Can two threads access a synchronized method at the same time?

It depends on what object instance the two threads are trying to lock on. Two threads cannot access the same synchronized method on the same object instance. One will get the lock and the other will block until the first thread leaves the method.

In your example, instance methods are synchronized on the object that contains them. In this case, when you call alphonse.bow(...) you are locking on the alphonse object. gaston.bow(...) locks gaston.

There are a couple of ways that you can get multiple instances of an object to lock on the same object.

  • You could make the method be static and synchronized in which case they would lock on the class object itself. There is only one of these objects per class loader.

    public static synchronized void bow(Friend bower) {
    
  • They could both lock on a defined static object. Something like:

    private static final Object lockObject = new Object();
    ...
    public void bow(Friend bower) {
        synchronized (lockObject) {
            ....
        }
    }
    
  • Or you could could pass in the object to lock on if you didn't want to make it static.

Your output could be something like the following:

  1. the gaston thread (may) start first and calls bow(alphonse)
  2. this locks the gaston object and outputs: Gaston: Alphonse has bowed to me!
  3. it calls alphonse.bowBack(this).
  4. this call locks the alphonse object and outputs: Alphonse: Gaston has bowed back to me!
  5. alphonse.bowBack(this) exits, unlocking the alphonse object.
  6. gaston.bow(alphonse) exits, unlocking the gaston object.
  7. then the gaston thread exits.
  8. the alphonse thread (may) start next and calls bow(gaston)
  9. this locks the alphonse object and outputs: Alphonse: Gaston has bowed to me!
  10. it calls gaston.bowBack(this).
  11. this call locks the gaston object and outputs: Gaston: Alphonse has bowed back to me!
  12. gaston.bowBack(this) exits, unlocking the gaston object.
  13. alphonse.bow(gaston) exits, unlocking the alphonse object.

This could happen in a number of different orders. The alphonse thread could run first even though it's start() method gets called at a later time. The only thing that the locks save you from is the calling of alphonse.bow(...) if alphonse.bowBack(...) is currently running. As @user988052 pointed out, because each thread locks their own object and then tries to lock the other, you can easily get a deadlock.


I didn't check your code in detail but I think I recognize the typical example as to how to create a deadlock.

However you shouldn't call it just once to try to create the deadlock.

Create threads in a loop and there's a very high probability you'll get your deadlock:

for ( int i = 0; i < 1000; i++ ) {
    final Friend alphonse =
        new Friend("Alphonse");
    final Friend gaston =
        new Friend("Gaston");
    new Thread(new Runnable() {
        public void run() { alphonse.bow(gaston); }
    }).start();
    new Thread(new Runnable() {
        public void run() { gaston.bow(alphonse); }
    }).start();
}

Note that you won't deadlock your 2000 threads: only some of them will be deadlocked. You can verify this by taking a threadump of your program/JVM.