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 issynchronizedon thealphonseFriendobject.  This means the Thread must acquire the lock from this object.
- The second Thread started calls gaston.bow(alphonse), which issynchronizedon thegastonFriendobject.  This means the Thread must acquire the lock from this object.
- The first thread started now calls bowbackand waits for the lock ongastonto be released.
- The second thread started now calls bowbackand waits for the lock onalphonseto 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- Friendinstances.  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 callsalphonse.bow(gaston), which issynchronizedon thealphonseFriendobject.  Thread #2 thus acquires the "lock" for thealphonseobject and enters thebowmethod.
- 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 thegastonFriendobject.  Since no-one has yet acquired the "lock" for thegastonobject instance, Thread #3 successfully acquires this lock and enters thebowmethod.
- A time slice occurs here and Thread #2 gets a chance to do more processing.
- Thread #2 now calls bower.bowBack(this);withbowerbeing a reference to the instance forgaston.  This is the logical equivalent of a call ofgaston.bowBack(alphonse).  Thus, this method issynchronizedon thegastoninstance.  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 ongastonto 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 callalphonse.bowBack(gaston).  To do this, it needs to acquire the lock for thealphonseinstance, 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.