/* Java 2: The Complete Reference
*  by H.Schildt and P.Naughton
*  Chapter 11: Multithreaded Programming
*/

// An example of deadlock.

// The class A has two synchronized methods:
// aMethod() and last()

class A {
  synchronized void aMethod(B b) {
    String name = Thread.currentThread().getName();

    System.out.println(name + " entered  aMethod()");

    try {
      Thread.sleep(1000);   // sleep for 1 sec
    } catch(Exception e) {
      System.out.println("A Interrupted");
    }

    System.out.println(name + " trying to call B.last()");

    b.last();   // try to call last() method of B 
  }

  synchronized void last() {
    System.out.println("Inside A.last");
  }
}


// The class B has two synchronized methods:
// bMethod() and last()

class B {
  synchronized void bMethod(A a) {
    String name = Thread.currentThread().getName();
    System.out.println(name + " entered  bMethod()");

    try {
      Thread.sleep(1000);
    } catch(Exception e) {
      System.out.println("B Interrupted");
    }

    System.out.println(name + " trying to call A.last()");

    a.last();    // try to call last() method of A
  }

  synchronized void last() {
    System.out.println("Inside B.last");
  }
}



class Deadlock implements Runnable {

  A a = new A();
  B b = new B();

  Deadlock() {
    Thread.currentThread().setName("MainThread");
    Thread t = new Thread(this, "RacingThread");
    t.start();

    a.aMethod(b);       // The main thread gets lock on "a"
			// and enters aMethod where it will sleep for 1 sec
			// before trying to call b.last()
    System.out.println("Back in main thread");
  }

  public void run() {
    b.bMethod(a);       // The second thread gets lock on b
			// when the main thread is sleeping 
			// and enters bMethod where it will sleep for 1 sec
			// before trying to call a.last()
    System.out.println("Back in other thread");
  }

  public static void main(String args[]) {
    new Deadlock();
  }

}