class Friendly {
private Friendly partner;
private String name;
public Friendly(String name) {
this.name = name;
}
public synchronized void hug() {
System.out.println(Thread.currentThread().getName()+
" in " + name + ".hug() trying to invoke " +
partner.name + ".hugBack()");
partner.hugBack();
}
private synchronized void hugBack() {
System.out.println(Thread.currentThread().getName()+
" in " + name + ".hugBack()");
}
public void becomeFriend(Friendly partner) {
this.partner = partner;
}
}
Now consider this scenario, in which jareth and cory are two Friendly objects that have become
friends:
Thread number 1 invokes synchronized method jareth.hug. Thread number 1 now has the
lock on jareth.
1.
Thread number 2 invokes synchronized method cory.hug. Thread number 2 now has the lock
on cory.
2.
Now jareth.hug invokes synchronized method cory.hugBack. THRead number 1 is now
blocked waiting for the lock on cory (currently held by thread number 2) to become available.
3.
Finally, cory.hug invokes synchronized method jareth.hugBack. Thread number 2 is
now blocked waiting for the lock on jareth (currently held by thread number 1) to become
available.
4.
We have now achieved deadlock: cory won't proceed until the lock on jareth is released and vice versa,
so the two threads are stuck in a permanent embrace.
We can try to set up this scenario:
public static void main(String[] args) {
final Friendly jareth = new Friendly("jareth");
final Friendly cory = new Friendly("cory");
jareth.becomeFriend(cory);
cory.becomeFriend(jareth);
new Thread(new Runnable() {
public void run() { jareth.hug(); }
}, "Thread1").start();
new Thread(new Runnable() {
public void run() { cory.hug(); }
}, "Thread2").start();
}