0

I have the following Thread example:

class Q
{
    int num;
    public synchronized void put(int num) {
        System.out.println("Put :"+num);
        this.num = num;
        try {Thread.sleep(100);} catch (Exception e) {}
        notify();
        try {wait();} catch (Exception e) {}
    }
    public synchronized void get() {
        try {wait();} catch (Exception e) {}
        System.out.println("Get :"+num);
        notify();
    }
}
class Producer implements Runnable
{
    Q q;
    public Producer(Q q) {
        this.q = q;
        Thread t = new Thread(this,"Producer");
        t.start();
    }
     public void run() {
         int i = 0;
         while(true) {
             q.put(i++);
                try {Thread.sleep(1000);} catch (Exception e) {}
         }  
     }
}
class Consumer implements Runnable
{
    Q q;
    Thread t;
    public Consumer(Q q) {
        this.q = q;
        t = new Thread(this,"Consumer");
        t.start();
    }
     public void run() {
         while(true) {
             q.get();
            try {Thread.sleep(500);} catch (Exception e) {}
         }     
     }
}
public class InterThread {
    public static void main(String[] args) {
        Q q = new Q();
        new Producer(q);
        new Consumer(q);
    }
}

I'm trying to run two threads, consumer and producer, in a loop. sharing the same object q, one thread incrementing q.num and printing the value of it, and the other is consuming q.num by just printing its value. The result I'm getting in a console is "Put :0" and stops there, consumer thread not being called, even though I used Thread.sleep(100); before calling notify() in the producer thread, why !!?

Govinda Sakhare
  • 5,009
  • 6
  • 33
  • 74
Helmi
  • 83
  • 9
  • 1
    You should pay attention to [the documentation of `wait`](https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html#wait--), especially the part: “*this method should always be used in a loop `while () wait();`*” Your code does not only fail to check the condition, there is not even a condition to check, as the producer is not producing anything and the consumer does not consume. All you have created, is some kind of counter. – Holger Jan 22 '20 at 17:55
  • yes, i know it's not the proper way to use `wait()` i just want to understand what this code is doing exactly. – Helmi Jan 22 '20 at 18:13
  • 1
    Never, ever call `sleep()` from within a _critical section_ (i.e., from inside a `synchronized` block or a `synchronized` method or, while keeping a `Lock` object locked.) The only exception would be if you were writing an example to demonstrate why it is a \*Bad Idea\* for a critical section to do anything that takes a long time. – Solomon Slow Jan 22 '20 at 22:19
  • Why are you waiting inside `put()` at all? Ask yourself. What exactly are you waiting *for,* and what are you going to do when it's over? A: nothing and nothing. – user207421 Jan 23 '20 at 03:09

1 Answers1

1

In this case, Producer thread is starting before Consumer. notify() is getting called, following by that wait() getting called. Producer thread goes in waiting state, releases acquired lock.

// producer
notify();
try {
   System.out.println(Thread.currentThread().getName() + " Put :"+num);
   this.wait(); // lock released
} 
catch (Exception e) {

}

Now consumer thread acquires the lock, wait() is executed. Consumer goes in the waiting state.

// consumer
try {
   System.out.println(Thread.currentThread().getName() + "Get :"+num);
   this.wait(); // Both the threads are waiting
} 
catch (Exception e) { 

}

Now both the threads are waiting for notify call from the other thread Note that Sleep() method doesn't release the lock , so there is no point in calling calling Thread.sleep before the producer's notify

difference-between-wait-and-sleep

Govinda Sakhare
  • 5,009
  • 6
  • 33
  • 74
  • why `try {Thread.sleep(100);} catch (Exception e) {} ` in producer can't make consumer thread goes in waiting state before `notify()` being called in producer. – Helmi Jan 22 '20 at 17:38
  • 1
    You're both the methods are `synchronized`, synchronized method needs lock on`this`. https://stackoverflow.com/questions/3047564/java-synchronized-method-lock-on-object-or-method – Govinda Sakhare Jan 22 '20 at 18:10
  • 1
    "Classic deadlock," would be when each of the other threads is waiting for the other to _release a resource_ that each of them needs. The OP's problem is different. Some authors call it "lost notification." The author expects that the one thread will wake the other by calling `notify()`, but the notification was delivered at a time when the second thread was not yet `wait()`ing for it, and so it's as if the notification never happened,. – Solomon Slow Jan 22 '20 at 22:16