Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Understanding Java Wait and Notify methods

I have a following program:

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;


public class SimpleWaitNotify implements Runnable {

final static Object obj = new Object();
static boolean value = true;

public synchronized void flag()  {
    System.out.println("Before Wait");
    try {
        obj.wait();
    } catch (InterruptedException e) {
        System.out.println("Thread interrupted");
    }
    System.out.println("After Being Notified");
}

public synchronized void unflag() {
    System.out.println("Before Notify All");
    obj.notifyAll();
    System.out.println("After Notify All Method Call");
}

public void run() {
    if (value) {
        flag();
    } else {
        unflag();
    }
}

public static void main(String[] args) throws InterruptedException {
    ExecutorService pool = Executors.newFixedThreadPool(4);
    SimpleWaitNotify sWait = new SimpleWaitNotify();
    pool.execute(sWait);
    SimpleWaitNotify.value = false;
    SimpleWaitNotify sNotify = new SimpleWaitNotify();
    pool.execute(sNotify);
    pool.shutdown();

}

}

When I wait on obj, I get the following exception Exception in thread "pool-1-thread-1" java.lang.IllegalMonitorStateException: current thread not owner for each of the two threads.

But if I use SimpleWaitNotify's monitor then the program execution is suspended. In other words, I think it suspends current execution thread and in turn the executor. Any help towards understanding what's going on would be duly appreciated.

This is an area1 where the theory and javadoc seem straightforward, and since there aren't many examples, conceptually left a big gap in me.

like image 788
Maddy Avatar asked Apr 12 '10 18:04

Maddy


1 Answers

You're calling wait and notifyAll on obj, but you're synchronizing on this (because you've got synchronized methods).

In order to wait or notify, you need to "own" the monitor first. Unsynchronize the methods, and synchronize on obj instead:

public void flag()  {
    System.out.println("Before Wait");
    synchronized (obj) {
        try {
            obj.wait();
        } catch (InterruptedException e) {
            System.out.println("Thread interrupted");
        }
    }
    System.out.println("After Being Notified");
}

public void unflag() {
    System.out.println("Before Notify All");
    synchronized (obj) {
        obj.notifyAll();
    }
    System.out.println("After Notify All Method Call");
}
like image 148
Jon Skeet Avatar answered Oct 07 '22 18:10

Jon Skeet