class A ... { synchronized void foo(B b)...{ String name=Thread.currentThread().getName(); System.out.println(name + " enter A.foo()"); try ...{ Thread.sleep(10); } catch (InterruptedException e) ...{ e.printStackTrace(); } System.out.println(name + " trying to call B.last()"); b.last(); } synchronized void last()...{ System.out.println("Inside A.last()"); }} class B ... { synchronized void bar(A a)...{ String name=Thread.currentThread().getName(); System.out.println(name + " enter B.bar()"); try ...{ Thread.sleep(10); } catch (InterruptedException e) ...{ e.printStackTrace(); } System.out.println(name + " trying to call A.last()"); a.last(); } synchronized void last()...{ System.out.println("Inside B.last()"); }} public class PcDead implements Runnable ... { A a = new A(); B b = new B(); PcDead()...{ Thread.currentThread().setName("Main thread:"); Thread t = new Thread(this,"Sub thread:"); t.start(); a.foo(b); System.out.println("Back in mian thread"); } public void run()...{ b.bar(a); System.out.println("Back in sub thread"); } public static void main(String[] args) ...{ new PcDead(); }}