Use of notify() and notifyAll() doesn’t work in the code

I pasted the code below. That is commented enough. Clear about wait(). When comes here it jumps to another block. That part i am oaky. My doubt is Why we are using notify and notifyAll(). If you remove these two from below code, it works fine.

class Reader extends Thread{
    Calculator c;
    //here we didn't write no-arg constructor.  Note this.
    // one - arg constructor.
    public Reader(Calculator calc){
        c = calc;
    }
    public void run(){
        synchronized(c){
        // 2. Acquiring the object lock and executes this code of block.
            try{
                System.out.println("Waiting for calculation...");
                c.wait();
                // 3.  Release the object lock and moves to the second synchronize block below
                // 6. Later the object get the lock here and moves on.
            }catch(InterruptedException e){
            }
            System.out.println("Total is: "+c.total);
        }
    }
    public static void main(String[] args){
        //Instantiating new with no-arg.  One more doubt,  How this work without no-arg constructor above.  Please explain.
        Calculator calculator = new Calculator();
        //Instantiating new with one-arg
        new Reader(calculator).start();
        new Reader(calculator).start();
        new Reader(calculator).start();
        // 1. Once you start here it will goto first synchronized code block above
        calculator.start();
    }
}

class Calculator extends Thread{
    int total;

    public void run(){
        synchronized(this){
        // 4. This block acquires that object lock and executes the code block below.

            for(int i=0;i<100;i++){
                total +=i;
            }
            // 5.  As per documentation,  If we give notify() it will release the object lock to only one thread object of its choice.
            //     If we use notifyAll(); it will release the object lock to all the three thread object.
            notify();
            // My doubt here is without using the notify or notifyAll it is working fine.
            // As per docs if we use notify() only one object should get the lock.  That is also not working here.
        }
    }
}

Answer

General comment: the javadoc of Object#wait states that

As in the one argument version, interrupts and spurious wakeups are possible, and this method should always be used in a loop.

So a waiting thread can wake up without being notified and your design should take that into account by waiting in a loop and checking for an exit condition (cf example in the javadoc).


In your case, however, the issue is slightly different. According to the Thread#join javadoc:

As a thread terminates the this.notifyAll method is invoked. It is recommended that applications not use wait, notify, or notifyAll on Thread instances.

So when your Calculator finishes, it calls this.notifyAll() and wakes up all the waiting threads.


How to fix it?

You should use a separate lock object, similar to: private final Object lock = new Object(); in your Calculator and provide a getter for the Readers.

Leave a Reply

Your email address will not be published. Required fields are marked *