I came across this example on Oracle\'s Java Tutorial describing Deadlock in multi threading scenarios.
So in this example I made following change at line 17 and lin
There is no difference in whether you use System.out.print
or System.out.format
: they're basically doing the same thing.
The deadlock occurs here if execution of Gaston.bow(Alphonse)
is started between the start of Alphonse.bow(Gaston)
and bower.bowBack(Alphonse)
(or vice versa): the two threads are waiting for a monitor held by the other, and thus deadlock occurs.
This happens inconsistently, because it depends upon a subtle timing issue, depending upon how the threads are scheduled - it is possible that Alphonse.bow
and bower.backBack(Alphonse)
complete before Gaston.bow
is executed, so it looks like there is no deadlock.
The classic way to fix this is to order the lock acquisition, so that the first the same lock is acquired first every time; this prevents the possibility of deadlock:
public void bow(Friend bower) { // Method no longer synchronized.
int firstHash = System.identityHashCode(this);
int secondHash = System.identityHashCode(bower);
Object firstMonitor = firstHash < secondHash ? this : bower;
Object secondMonitor = firstHash < secondHash ? bower : this;
synchronized (firstMonitor) {
synchronized (secondMonitor) {
// Code free (*) of deadlocks, with respect to this and bower at least.
}
}
}
(*) It's not quite guaranteed to be deadlock free, since System.identityHashCode
can return the same value for distinct objects; but that's reasonably unlikely.
It's an application of the Birthday paradox: if you've got just two monitors, the chance of collision is something like 10^-18; but if you've got >77k monitors, a collision is more likely than not.