0

I am learning multi threading and I am trying to understand how to use wait and notify methods of Object class. I have gone through this link https://www.journaldev.com/1037/java-thread-wait-notify-and-notifyall-example and have written the following program

Waiter

public class Waiter implements Runnable {
    private Message m;
    public Waiter(Message m) {
         this.m = m;
    }
    public void run() {
        String name = Thread.currentThread().getName();
        System.out.println(t1 + " thread waiting for message");
        synchronized (m) {
            try {
                m.wait();
                System.out.println(t1 + " " + m.getText());
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        System.out.println(t1 + " thread waiting for message");
    }
}

Notifier

public class Notifier implements Runnable {
    private Message m;
    public Notifier(Message m) {
         this.m = m;
    }
    public void run() {
        synchronized (m) {
            try {
                Thread.sleep(2000);
                m.notifyAll();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

Test

public class WaitNotifyTest {
    public static void main(String[] str) {
        Message m = new Message("hello");
        new Thread(new Waiter(m), "t1").start();
        new Thread(new Waiter(m), "t2").start();
        new Thread(new Notifier(m)).start();
    }
}

When I execute the program, it sometimes terminates properly, sometimes it waits indefinitely, sometimes one of the thread terminates and the other waits indefinitely. Can anyone please tell me what is wrong here?

Also I want to know few examples of real time applications of wait and notify methods.

Krishna Chaitanya
  • 2,533
  • 4
  • 40
  • 74
  • I think the issue is with Thread.sleep(2000) in synchronized block of Notifier class. Once I moved it outside of the synchronized block, the program terminates properly always. Can anyone please tell me what is the difference here? – Krishna Chaitanya Nov 30 '17 at 08:51
  • Assume `Notifier` thread runs first, and enters into `synchronized (m)` section. `Waiter` thread cannot enter this section until `Notifier` leaves it. But at the time of leaving, `m.notifyAll()` is **already performed**. So, when `Waiter` enters the section and performs `m.wait()`, it will wait *forever*: no one will notify the thread after that. By moving `Thread.sleep(2000)` outside of the section you make given scenario much less possible: While `Notifier` sleeps **outside of the critical section**, there is a high chance for `Waiter` to enter the section first. – Tsyvarev Nov 30 '17 at 09:43

1 Answers1

1

when you are doing wait best practice is do in a while loop with a condition.There can be scenario where thread will notify and after that other thread enter wait state.So thread will go always in wait state

Modified code:

public class Waiter implements Runnable {
    private Message m;

    public Waiter(Message m) {
        this.m = m;
    }

    public void run() {
        String name = Thread.currentThread().getName();
        System.out.println(name + " thread waiting for message");
        synchronized (m) {
            try {
                while (m.getText() == null) {
                    m.wait();
                }
                System.out.println(name + " " + m.getText());
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        System.out.println(name + " thread waiting for message");
    }
}

public class Notifier implements Runnable {
    private Message m;

    public Notifier(Message m) {
        this.m = m;
    }

    public void run() {
        synchronized (m) {

            m.setText("hello");
            m.notifyAll();

        }
    }
}

public class WaitNotifyTest {
    public static void main(String[] str) {
        Message m = new Message();
        new Thread(new Waiter(m), "t1").start();
        new Thread(new Waiter(m), "t2").start();
        new Thread(new Notifier(m)).start();
    }
}
gati sahu
  • 2,576
  • 2
  • 10
  • 16
  • When I moved Thread.sleep to outside of the synchronized block and the program terminated properly. Alternatively, I followed your suggestion, moved back Thread.sleep to synchronized and added the loop and the program terminated fine. I am not able to understand what's the difference between having Thread.sleep inside and outside the synchronized block. – Krishna Chaitanya Nov 30 '17 at 09:11
  • when you use thread sleep It always pause the current thread execution and thread sleep doesn’t lose any monitors or locks current thread has acquired. So it becomes high probable that wait execute after notifier. – gati sahu Nov 30 '17 at 09:12
  • @gati sahu - Since the code uses notifyAll() wouidn't it invoke all waiting threads. Also the posted code works fine for me without blocking. The only possibility i can think of is if the notify is processed before the thread's wait(). – Sekar Nov 30 '17 at 09:14
  • @gatisahu I am sorry to say that I did not understand. I am new to multithreading. I only have theorotical knowledge. Can you please explain in detail? – Krishna Chaitanya Nov 30 '17 at 09:20