Understanding Java Wait and Notify Methods

I have the 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 the SimpleWaitNotify monitor, then the execution of the program is suspended. In other words, I think it pauses the current thread of execution and, in turn, the executor. Any help in understanding what is going on will be duly appreciated.

This is an area1 where theory and javadoc seem simple, and since there are not many examples, conceptually left a big gap in me.

+7
java multithreading wait
source share
3 answers

You call wait and notifyAll on obj , but you are synchronizing on this (because you have synchronized methods).

To wait or notify, you first need to "own" the monitor. Unsynchronize methods and instead sync to obj:

 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"); } 
+12
source share

Either synchronize on obj , or call wait and notify on this . The calling thread must contain a monitor of the same object on which these methods are called.

For example,

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

In this example, the lock is held on this (when the synchronized modifier is used in the instance method, the instance monitor will be retrieved). Thus, the wait() method can be called on an alleged instance of this .


In order to coordinate the two threads, they need to share the same lock. The original version had a static obj that could be used as a lock, but was not used in synchronized blocks. Here is a better example:

 class SimpleWaitNotify implements Runnable { private final Object lock; private final boolean wait; SimpleWaitNotify(Object lock, boolean wait) { this.lock = lock; this.wait = wait; } public void flag() { synchronized (lock) { System.out.println("Before Wait"); try { lock.wait(); System.out.println("After Being Notified"); } catch (InterruptedException ex) { System.out.println("Thread interrupted"); } } } public void unflag() { synchronized(lock) { System.out.println("Before Notify All"); lock.notifyAll(); System.out.println("After Notify All Method Call"); } } public void run() { if (wait) { flag(); } else { unflag(); } } public static void main(String[] argv) throws Exception { ExecutorService pool = Executors.newFixedThreadPool(4); Object shared = new Object(); SimpleWaitNotify sWait = new SimpleWaitNotify(shared, true); pool.execute(sWait); SimpleWaitNotify sNotify = new SimpleWaitNotify(shared, false); pool.execute(sNotify); pool.shutdown(); } } 
+3
source share

Rather, placing the direct pool.shutdown() statement, try as shown below.

 while (!service.isTerminated()) { service.shutdown(); } 

Thus, it will wait until all threads have completed execution.

+1
source share

All Articles