OhioState22
OhioState22

Reputation: 43

Java - using wait() and notify()

THIS IS NOT A DUPLICATE OF Java, Multithreading with synchronized methods... he didn't ask the same question.

I am trying to write a program that using multi-threading and deadlocks. I am having trouble understanding how and where to use wait() and notify() in my synchronized methods to have the thread wait and wake it up with notify(). I have it to make the first thread wait after the ping statement so the next thread will start it's ping statement too. But I have a notify() to wake up the first thread and I can't figure out why the thread will not wake up. The following is suppose to be my output:

Starting...1
Girl (ping): pinging Boy
Boy (ping): pinging Girl
Girl (ping): asking Boy to confirm
Boy (confirm): confirm to Girl
Girl (ping): got confirmation
Boy (ping): asking Girl to confirm
Girl (confirm): confirm to Boy
Boy (ping): got confirmation

My code is deadlocking or I am not using wait and notify correctly because it stops here:

Starting...1
Girl (ping): pinging Boy
Boy (ping): pinging Girl
Girl (ping): asking Boy to confirm
Boy (confirm): confirm to Girl
Girl (ping): got confirmation

Here is my code:

Monitor.java

class Monitor {
String name;

   public Monitor (String name) { this.name = name; }

   public String getName() {  return this.name; }

   public synchronized void ping (Monitor p) {
      p.release(p);
      System.out.println(this.name + " (ping): pinging " + p.getName());
      notify();
      try { wait(); } catch (Exception e) {}
      System.out.println(this.name + " (ping): asking " + p.getName() + " to confirm");
      p.confirm(p);
      System.out.println(this.name + " (ping): got confirmation");
   }

   public synchronized void confirm (Monitor p) {
      System.out.println(this.name + " (confirm): confirm to " + p.getName());
   }

   public synchronized void release (Monitor p) {
      notify();
   }
}

Runner.java

public class Runner extends Thread {
Monitor m1, m2;

    public Runner (Monitor m1, Monitor m2) { 
      this.m1 = m1; 
      this.m2 = m2; 
    }

    public void run () {  
       m1.ping(m2);  
    }
}

Deadlock.java

public class DeadLock {
   public static void main (String args[]) {
      int i=1;
      System.out.println("Starting..."+(i++));
      Monitor a = new Monitor("Girl");
      Monitor b = new Monitor("Boy");
      (new Runner(a, b)).start();
      (new Runner(b, a)).start();
   }
}

Upvotes: 0

Views: 445

Answers (2)

Gray
Gray

Reputation: 116908

You are calling:

(new Runner(a, b)).start();
// which effectively calls in run()
a.ping(b);

This locks a calls notify on a and then waits on a.

The other thread calls:

(new Runner(b, a)).start();
// which effectively calls in run()
b.ping(a);

This locks b calls notify on b and then waits on b.

Since neither of the threads is notifying the other one, they will never leave that state. I'm not sure what you are trying to accomplish so it's hard to figure out how to fix the code.

Edit:

Now that you've edited your code you have a more standard deadlock.

  • The first thread locks a then tries to lock b to notify it.
  • The second thread locks b then tries to lock a to notify it.

Each thread has their lock but needs the other lock to continue. Classic deadlock.

I suggest that you learn to use the debugger @OhioState22. Set break points and step through your code. Here's a decent Eclipse tutorial.

Upvotes: 1

Καrτhικ
Καrτhικ

Reputation: 3915

As a rule avoid using Java's wait() and notify() and prefer one of Java 5's concurrency features instead, e.g. ReentrantLock. The reason is that if a thread calls notify() before your thread hits wait(), the subsequent call to wait() will block and depending on your algorithm, indefinitely. Lookup the javadocs for RenetrantLock

Upvotes: 0

Related Questions