2

I am still learning on Threads following java tutorials of oracle website.

With regarding to the wait() and notifyAll(), I have written some code. My expected output is print the message in run() 10 times and print the "Fun stopped by StopFun Thread" message in guardedJoy(GuardedBlock guardedBlock) method when the 'joy' set to false in the run method.

This is my code.

public class GuardedBlock {

private boolean joy = true;

public synchronized void guardedJoy(GuardedBlock guardedBlock) {

    System.out.println(Thread.currentThread().getName() + " Guard Joy method started");
    while (guardedBlock.joy) {
        try {
            System.out.println(Thread.currentThread().getName() + " Going to waiting state");
            guardedBlock.wait();
        } catch (InterruptedException ex) {
        }
    }
    System.out.println("Fun stopped by StopFun Thread");
}

private static class StopFun implements Runnable {

    private GuardedBlock guardedBlock;

    public StopFun(GuardedBlock guardedBlock) {
        this.guardedBlock = guardedBlock;
    }

    @Override
    public void run() {

        for (int x = 0; x < 100; x++) {
            try {
                Thread.sleep(500);
                System.out.println("Allowing fun since its only " + x + " times - " + Thread.currentThread().getName());

                if (x == 10) {
                    guardedBlock.joy = false;
                    guardedBlock.notifyAll();
                    break;
                }
            } catch (InterruptedException ex) {
            }
        }
    }
}

public static void main(String[] args) {

    GuardedBlock guardedBlock = new GuardedBlock();

    StopFun sf = new StopFun(guardedBlock);
    Thread stopFun = new Thread(sf);
    stopFun.start();

    guardedBlock.guardedJoy(guardedBlock);
    }
}

The code in the run method runs fine but afterwards it throws an exception like this.

Exception in thread "Thread-0" java.lang.IllegalMonitorStateException
    at java.lang.Object.notifyAll(Native Method)
    at Synchronization.GuardedBlock$StopFun.run(GuardedBlock.java:38)
    at java.lang.Thread.run(Thread.java:748)

I went through couple of questions and answers in the site like this and this but could not figure out what exactly I am doing wrong. A help is much valued.

Thanks.

Ran_Macavity
  • 154
  • 2
  • 21
  • [The documentation](https://docs.oracle.com/javase/9/docs/api/java/lang/Object.html#notifyAll--) is your friend: “**Throws:** IllegalMonitorStateException - if the current thread is not the owner of this object's monitor.” – VGR Nov 21 '17 at 22:13

1 Answers1

3

wait() and notify()/notifyAll() must be called in a synchronized block.

synchronized (guardedBlock) {
    guardedBlock.notifyAll();
}

and so on.

Roman Puchkovskiy
  • 11,415
  • 5
  • 36
  • 72
  • Thanks for the answer. I have a question though.wait() is already in a synchronized method. So do I need to introduce a separate synchronized block? – Ran_Macavity Nov 21 '17 at 19:21
  • Sorry, I did not see that the method is synchronized. But it is synchronized on `this`, and `wait()` is called on `guardedBlock`. In your program is so happens that `guardedBlock` matches `this` at the moment of the call due to `guardedBlock.guardedJoy(guardedBlock);`, and it should work without an additional `synchronized` block, but this is a bit fragile. And of course, `notifyAll()` must be under synchronization as well. – Roman Puchkovskiy Nov 21 '17 at 19:27
  • It's better to place `guardedBlock.joy = false;` in synchronized block as well. – Mikita Harbacheuski Nov 21 '17 at 20:17
  • Thanks both of you for the clarification :) – Ran_Macavity Nov 23 '17 at 04:45
  • Did you ever figure this out because I'm using your code and placed the call to notifyAll() in a synchronized method and still receive the error... – Mihael Keehl Jul 06 '20 at 19:58