0

I have been learning multithreading in Java since recently and I encountered an example in the book. It goes something like this.

class NewThread implements Runnable {
String name;
Thread t;
boolean suspendFlag;
NewThread(String threadname) {
    name = threadname;
    t = new Thread(this, name);
    System.out.println("New thread: " + t);
    suspendFlag = false;
    t.start();
}

public void run() {
    try {
        for(int i = 15; i > 0; i--) {
            System.out.println(name + ": " + i);
            Thread.sleep(200);
            synchronized(this) {
                while(suspendFlag) {
                    wait();
                }
            }
        }
    } catch (InterruptedException e) {
        System.out.println(name + " interrupted.");
    }
    System.out.println(name + " exiting.");
}
synchronized void mysuspend() {
    suspendFlag = true;
}
synchronized void myresume() {
    suspendFlag = false;
    notify();
}
}

class Te {
    public static void main(String args[]) {
        NewThread ob1 = new NewThread("One");
        NewThread ob2 = new NewThread("Two");
        try {
            Thread.sleep(1000);
            ob1.mysuspend();
            System.out.println("Suspending thread One");
            Thread.sleep(1000);
            ob1.myresume();
            System.out.println("Resuming thread One");
            ob2.mysuspend();
            System.out.println("Suspending thread Two");
            Thread.sleep(1000);
            ob2.myresume();
            System.out.println("Resuming thread Two");
        } catch (InterruptedException e) {
            System.out.println("Main thread Interrupted");
        }
        try {
            System.out.println("Waiting for threads to finish.");
            ob1.t.join();
            ob2.t.join();
        } catch (InterruptedException e) {
            System.out.println("Main thread Interrupted");
        }
        System.out.println("Main thread exiting.");
    }

}

Now in this example as you can see, there is a resume and a suspend method which gets called a couple of times in the program's main method. But when I remove the synchronized block in the run method, it displays an error something like this.

Exception in thread "Two" java.lang.IllegalMonitorStateException

I acually wanted to know, why do we need the synchronized block for the while statement. Doesn't the while resume when the value of suspendFlag change?

  • 2
    [Read the Javadoc of `wait()`](https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html#wait--) – Andy Turner Jun 08 '18 at 12:21
  • 1
    https://stackoverflow.com/questions/1537116/illegalmonitorstateexception-on-wait-call – Sneftel Jun 08 '18 at 12:25
  • Technically `mysuspend` doesn't need to be synchronized, because having `suspendFlag` set to `true` between the while check and the `wait` is harmless, as `suspendFlag` must be `true` already at that point. – jingx Jun 08 '18 at 13:54

1 Answers1

1

Here's what could happen if there was no synchronization:

Thread A could check suspendFlag and find it to be true,

Thread B could set suspendFlag=false; and then call notify();

Thread A could then call wait() (because suspendFlag was true when it checked.), and now Thread A is hung, waiting for a notification that will never happen.

The synchronization prevents thread B from changing the suspendFlag in between the moment when thread A checked it, and the moment when thread A actually begins to wait for the notification.

Solomon Slow
  • 25,130
  • 5
  • 37
  • 57