2

This code comes from Oracle tutorial about concurrency. I don't understand why synchronizing methods leads to deadlock. When methods are not synchronized everything works fine, but when I add synchronized keyword, program stops and method bowBack() is never invoked. Could someone explain in affordable manner why it happens? Below is mentioned code snippet:

public class Deadlock {
    static class Friend {
        private final String name;

        Friend(String name) {
            this.name = name;
        }

        String getName() {
            return this.name;
        }

        synchronized void bow(Friend bower) {
            System.out.format("%s: %s"
                        + "  has bowed to me!%n",
                this.name, bower.getName());
            bower.bowBack(this);
        }

        synchronized void bowBack(Friend bower) {
            System.out.format("%s: %s"
                        + " has bowed back to me!%n",
                this.name, bower.getName());
        }
    }

    public static void main(String[] args) {
        final Friend alphonse =
            new Friend("Alphonse");
        final Friend gaston =
            new Friend("Gaston");
        new Thread(() -> alphonse.bow(gaston)).start();
        new Thread(() -> gaston.bow(alphonse)).start();
    }
}
k13i
  • 4,011
  • 3
  • 35
  • 63

3 Answers3

6
  • thread 1: alphonse.bow(gaston) -> thread 1 holds the lock on alphonse, since bow() is synchronized
  • thread 2 : gaston.bow(alphonse) -> thread 2 holds the lock on gaston, since bow() is synchronized
  • thread 1 : gaston.bowBack(alphonse) -> blocks, since bowBack is synchronized, and thread 1 thus needs to get the lock of gaston, already held by thread 2
  • thread 2 : alphonse.bowBack(gaston) -> blocks, since bowBack is synchronized, and thread 2 thus needs to get the lock of alphonse, already held by thread 1

So both threads are blocked waiting for the other to release a lock.

JB Nizet
  • 678,734
  • 91
  • 1,224
  • 1,255
2

Deadlock happens because threads are trying to acquire the same resources in different order.

You have two resources here - alphonse and gaston. Synchronized method bow acquires a lock on its own object, and then calls bowBack, which acquires a lock on the opposite object.

  • First thread acquires a lock on gaston, and prepares to acquire a lock on alphonse
  • Second thread acquires a lock on alphonse, and prepares to acquire a lock on gaston

At this point, both threads are waiting for one another to release the lock on their object. However, neither one is about to do that before acquiring the lock on the opposite object, thus causing a deadlock:

Gridlock

Above: each of the two turning cars has occupied its corner of the intersection, and is waiting to drive into the opposite corner of the intersection before vacating its own.

Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
1

A synchronized method means that it locks the object instance that's running it.

Hence, the moment you call bow on each Friend, it locks itself. Then each Friend instance try to bowBack, but the other one is locked by its own bow and therefore cannot be called.

At this situation both threads are waiting for a resource to unlock. As they're actually waiting each other's resources, this is a deadlock.

GalAbra
  • 5,048
  • 4
  • 23
  • 42