How does synchronized work in Java

deadlock, java, multithreading

Solution

In Java, each `Object` provides the ability for a Thread to `synchronize`, or lock, on it. When a method is synchronized, the method uses its object instance as the lock. In your example, the methods `bow` and `bowBack` are both `synchronized`, and both are in the same class `Friend`. This means that any Thread executing these methods will synchronize on a `Friend` instance as its lock.

A sequence of events which will cause a deadlock is:

- The first Thread started calls `alphonse.bow(gaston)`, which is `synchronized` on the `alphonse` `Friend` object. This means the Thread must acquire the lock from this object.

- The second Thread started calls `gaston.bow(alphonse)`, which is `synchronized` on the `gaston` `Friend` object. This means the Thread must acquire the lock from this object.

- The first thread started now calls `bowback` and waits for the lock on `gaston` to be released.

- The second thread started now calls `bowback` and waits for the lock on `alphonse` to be released.

To show the sequence of events in much more detail:

- `main()` begins to execute in the main Therad (call it Thread #1), creating two `Friend` instances. So far, so good.

- The main Thread starts its first new Thread (call it Thread #2) with the code `new Thread(new Runnable() { ...`. Thread #2 calls `alphonse.bow(gaston)`, which is `synchronized` on the `alphonse` `Friend` object. Thread #2 thus acquires the "lock" for the `alphonse` object and enters the `bow` method.

- A time slice occurs here and the original Thread gets a chance to do more processing.

- The main Thread starts a second new Thread (call it Thread #3), just like the first one. Thread #3 calls `gaston.bow(alphonse)`, which is synchronized on the `gaston` `Friend` object. Since no-one has yet acquired the "lock" for the `gaston` object instance, Thread #3 successfully acquires this lock and enters the `bow` method.

- A time slice occurs here and Thread #2 gets a chance to do more processing.

- Thread #2 now calls `bower.bowBack(this);` with `bower` being a reference to the instance for `gaston`. This is the logical equivalent of a call of `gaston.bowBack(alphonse)`. Thus, this method is `synchronized` on the `gaston` instance. The lock for this object has already been acquired and is held by another Thread (Thread #3). Thus, Thread #2 has to wait for the lock on `gaston` to be released. The Thread is put into a waiting state, allowing Thread #3 to execute further.

- Thread #3 now calls `bowback`, which in this instance is logically the same as the call `alphonse.bowBack(gaston)`. To do this, it needs to acquire the lock for the `alphonse` instance, but this lock is held by Thread #2. This Thread is now put into a waiting state.

And you are now in a position where neither Thread can execute. Both Thread #2 and Thread #3 are waiting for a lock to be released. But neither lock can be released without a Thread making progress. But neither thread can make progress without a lock being released.

Thus: Deadlock!

Deadlocks very often depend on a specific sequence of events occurring, which can make then difficult to debug since they can be difficult to reproduce.

Problem

First, here's a sample: ``` public class Deadlock { static class Friend { private final String name; public Friend(String name) { this.name = name; } public String getName() { return this.name; } public synchronized void bow(Friend bower) { System.out.format("%s: %s has bowed to me!%n", this.name, bower.getName()); bower.bowBack(this); } public 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(new Runnable() { public void run() { alphonse.bow(gaston); } }).start(); new Thread(new Runnable() { public void run() { gaston.bow(alphonse); } }).start(); } } ``` What I don't get is how the blockage occurs. The main function initiates two threads that each begin their own bows. What exactly does 'synchronized' block? The same function running for the same object (as I originally thought)? The same function for all objects of the same class? All synchronized functions for the same object? All synchronized functions for all objects of the same class? Help me out here.

Original source

Related problems