reason of IllegalMonitorStateException if I use wait within sync block
Solution 1
You are synchronizing on monitor
, so you should wait()
on monitor, too:
monitor.wait();
Right now you are waiting on this
, which is not the owner of the monitor because synchronization is on monitor
.
Note that of course the notify
should also be done on the monitor
object, and that you might want to consider using notify
/notifyAll
in both threads. Otherwise it may happen that one thread starves waiting for a missing notification. Using a timeout (the overloaded version of wait
) might also be a good idea to catch corner cases.
Solution 2
The reason - The current thread is not the owner of the object's monitor
.To call wait()
method the current thread must own this object's monitor.
In your case you are obtaining monitor on monitor
object instead current object(this object).
gstackoverflow
Updated on June 04, 2022Comments
-
gstackoverflow almost 2 years
I try to understand java core synchronization.
I wrote code sample:
Program should write
left right
10 times
package concurrency; public class LeftRightWaitNotifyExample { final static String str = "1"; public static void main(String[] args) { new LeftLegThread(str).start(); new RightLegThread(str).start(); } } class LeftLegThread extends Thread { String monitor; public LeftLegThread(String str) { monitor = str; } @Override public void run() { try { makeStep(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } private void makeStep() throws InterruptedException { synchronized (monitor) { for (int i = 0; i < 10; i++) { System.out.println("Left "); wait(); } } } } class RightLegThread extends Thread { String monitor; public RightLegThread(String str) { monitor = str; } @Override public void run() { try { makeStep(); } catch (InterruptedException e) { } } private void makeStep() throws InterruptedException { synchronized (monitor) { while (true) { System.out.println("Right "); notify(); wait(); } } } }
I get this output:
Left Right Exception in thread "Thread-0" java.lang.IllegalMonitorStateException at java.lang.Object.wait(Native Method) at java.lang.Object.wait(Object.java:485) at concurrency.LeftLegThread.makeStep(LeftRightWaitNotifyExample.java:35) at concurrency.LeftLegThread.run(LeftRightWaitNotifyExample.java:23) Exception in thread "Thread-1" java.lang.IllegalMonitorStateException at java.lang.Object.notify(Native Method) at concurrency.RightLegThread.makeStep(LeftRightWaitNotifyExample.java:61) at concurrency.RightLegThread.run(LeftRightWaitNotifyExample.java:51)
Before I got this error when I used
wait
method non withinsynchronized
block. But here I use wait withinsynchronized
blockWhat is the cause of the problem and how to fix it?
update
I rewrite code according advice:
public class LeftRightWaitNotifyExample { final static String str = "1"; public static void main(String[] args) throws InterruptedException { new LeftLegThread(str).start(); Thread.sleep(100); new RightLegThread(str).start(); } } class LeftLegThread extends Thread { String monitor; public LeftLegThread(String str) { monitor = str; } @Override public void run() { try { makeStep(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } private void makeStep() throws InterruptedException { synchronized (monitor) { for (int i = 0; i < 2; i++) { System.out.println("Left "); monitor.wait(); monitor.notify(); } } } } class RightLegThread extends Thread { String monitor; public RightLegThread(String str) { monitor = str; } @Override public void run() { try { makeStep(); } catch (InterruptedException e) { } } private void makeStep() throws InterruptedException { synchronized (monitor) { while (true) { System.out.println("Right "); monitor.notify(); monitor.wait(); } } } }
current output:
Left Right Left Right Right
Why does
Right
outs 3 butLeft
only twice. Why? -
gstackoverflow about 10 yearsI have misunderstanding. I can use wait only on synchronized(this) ?
-
gstackoverflow about 10 yearsreally. amazing. But after replacing I see **Left Right Left ** and program is freezes
-
Prabhaker A about 10 years@gstackoverflow No you can use any object but the rule is
you have to call wait() method on object which is synchronized
.