1

Given a thread has multiple states: alive runnable running waiting and terminated. the notifyAll() method is suppose to put all threads that are "waiting" on an object's lock back into the "runnable" state where it is may be chosen as the next running object. The following example instantiates and starts 3 Reader threads, which go into waiting (wait() method) until the 'calc' object's lock is released. The calc objects thread is instantiated and started just after this where it adds up some numbers, followed by notifyAll().

My question is, why doesn't the calc thread notify all the Reader threads every time? when I run this on my computer it's hit and miss.

public class Reader extends Thread{
    Calculator c;

    public Reader(Calculator calc){
        c=calc;
    }

    public void run(){
        synchronized(c){
            try{
                System.out.println("Waiting for calculation...");
                c.wait();
            }catch(InterruptedException e){}
            System.out.println("Total is: "+c.total);
        }
    }
    public static void main(String[] args){
        Calculator calc = new Calculator();
        new Reader(calc).start();
        new Reader(calc).start();
        new Reader(calc).start();
        new Thread(calc).start();
    }
}
class Calculator implements Runnable{
    int total;

    public void run(){
        synchronized(this){
            for(int i =0; i<100; i++){
                total+=i;
            }
            notifyAll();
        }
    }
}
JensD
  • 205
  • 1
  • 5
  • 14
  • `notifyAll()` does _not_ immediately make threads RUNNABLE. It effectively changes their state from WAITING to BLOCKED. An `o.wait()` call in thread A can not return until thread A acquires the lock on object `o`, but it _can't_ do that at the moment when thread B calls `o.notifyAll()` because thread B must be holding the lock in order to make that call. – Solomon Slow Jul 28 '16 at 13:10
  • Please check out [Liedman's answer](https://stackoverflow.com/a/37046/8075923) to [Java: notify() vs. notifyAll() all over again](https://stackoverflow.com/questions/37026/java-notify-vs-notifyall-all-over-again). – Soutzikevich Jan 09 '19 at 20:02

2 Answers2

1

When executing multiple threads, order of execution of the threads is not guaranteed.

In your case chances are that the Calculator thread completes it's loop and calls notifyAll() even before any of the Reader threads gets into runnable state. So all Reader will keep waiting and will never print total.

To avoid such situation, in this particular example you can use another flag isCalculated in Calculator and set this flag once computation is done. Reader threads will also check for this flag and wait only when isCalculated is false.

class Reader extends Thread {
  Calculator c;

  public Reader(Calculator calc) {
    c = calc;
  }

  public void run() {
    synchronized (c) {
      try {
        System.out.println("Waiting for calculation...");

        if (!c.isCalculated) { // wait only if calculation is not done
          c.wait();
        }
      } catch (InterruptedException e) {
      }
      System.out.println("Total is: " + c.total);
    }
  }
}

class Calculator implements Runnable {
  int total;
  boolean isCalculated;

  public void run() {
    synchronized (this) {
      for (int i = 0; i < 100; i++) {
        total += i;
      }

      isCalculated = true;  // set flag to mark that computation is complete
      notifyAll();
    }
  }
}
justAbit
  • 4,226
  • 2
  • 19
  • 34
0

As mentioned by @Sudhir you can check some flags before calling wait , check this tutorial: http://docs.oracle.com/javase/tutorial/essential/concurrency/guardmeth.html

In your case notifyAll() may be called before wait is called .. so the threads may keep on waiting for the notify to be called

Shivam Jari
  • 101
  • 11
  • Concurrency is the next chapter in my book(sierra k bates b java 7). It's a really good book to prepare for my OCP. Perhaps I jumped the gun by asking this question, where all will be revealed shortly. However the sample code did ring alarm bells. – JensD Jul 28 '16 at 05:24