Reputation: 1028
I want to have such kind of work flow using explicit lock/condition variables (It's a course project which mandates this style.): A is the main class, it asks B to do some job from time to time. B has a worker class C which constantly queries B about new jobs to do and do it. After C finishes, it will call A's callback function to notify A the job is done.
However when I try to run the program, I get an IllegalMonitorStateException, when the callback() is trying to notify the doit() function.
exception in thread "Thread-0" java.lang.IllegalMonitorStateException
at java.lang.Object.notifyAll(Native Method)
at Test$A.callback(Test.java:49)
at Test$C.run(Test.java:115)
I looked at the javadoc and some Q&A about this exception, but still no idea why I get this.
import java.util.*;
import java.util.concurrent.locks.ReentrantLock;
import java.util.concurrent.locks.Condition;
public class Test {
public class A
{
private ReentrantLock lock;
private Condition cond;
private boolean bool;
private B b;
public A()
{
this.lock = new ReentrantLock();
this.cond = lock.newCondition();
b = new B(this);
bool = false;
}
public void doit()
{
try {
lock.lock();
b.letgo();
while (!bool) {
System.out.println("A::doit() Block.");
cond.awaitUninterruptibly();
}
System.out.println("A::doit() Done.");
}
finally {
lock.unlock();
}
}
public void callback() {
try {
lock.lock();
bool = true;
cond.notify();
System.out.println("A::callback() done.");
}
finally {
lock.unlock();
}
}
}
public class B
{
private C c;
private ReentrantLock lock;
private Condition cond;
private boolean bool;
public B(A a)
{
this.lock = new ReentrantLock();
this.cond = lock.newCondition();
bool = false;
c = new C(a, this);
c.start();
}
public void letgo()
{
try {
lock.lock();
bool = true;
}
finally {
lock.unlock();
}
}
public void get()
{
try {
lock.lock();
while (!bool) {
cond.awaitUninterruptibly();
}
bool = false;
return;
}
finally {
lock.unlock();
}
}
}
public class C extends Thread
{
private A a;
private B b;
public C(A a, B b)
{
this.a = a;
this.b = b;
}
public void run()
{
while (true) {
b.get();
a.callback();
}
}
}
public static void main(String args[])
{
Test t = new Test();
t.test1();
}
public void test1()
{
A a = new A();
a.doit();
}
}
Upvotes: 2
Views: 3761
Reputation: 269637
Use the signal()
method on Condition
in place of notify()
.
While you can successfully synchronize
on a Condition
instance, and then use the traditional wait()
and notify()
methods, you might as well just use an Object
if you aren't using the extended capabilities of the concurrent classes.
Condition
was intended to be used with the equivalent methods await()
and signal()
, and their enhanced variants.
Upvotes: 4