I think the call to
condition.signal();
in this code will always throw this exception. You
should never be catching this exception explicitly, it is intended to inform you
when you have a logic error in your use of a condition. If you look at the
docs for Condition.await()/signal()/signalAll(), it says that the owning lock,
in this case "lock", must be held by the current thread before a call to
any of the above functions. Failure to do this results in the
exception.
When the X thread is in await() it will release the lock
and go into a wait-state, in this case it will wait until signal() is called on
the Condition or the await() times out. When this happens it will wake up,
reaquire the lock and continue (you later release the lock again
correctly). It will wait to reacquire the lock if something else holds
it. It is done this way to avoid race conditions where a call
to await() could "miss" a call to signal().
In short to avoid the exception you should acquire the lock
in your Parse thread before calling signal() and release it immediatly after in
a finally block.
Also worth noting that to make a thread sleep for a period
of time Thread.sleep() is better and safer than using synchronized + wait()
as it won't interfere with anything else using "this" as a synchornization
object.
HTH.
Hi,
Firstly let me say that I'm really happy to find this
list. I find threading
difficult, but I'm trying to get to trips with it as
best I can, and I'm sure
this list will help my minisule
understanding...
Okay, I am trying to get to trips with the concurrency
features in Java
1.5, and I've got an issue that I'm trying to understand. I
have this
basic program structure...
....
....
private Lock lock
= new ReentrantLock();
private Condition condition =
lock.newCondition();
....
Parser parser = new
Parser(condition);
lock.lock();
try {
new
Thread(parser).start();
if(!condition.await(2000,
TimeUnit.MILLISECONDS)) {
if(parser.isReading())
{
if(!condition.await(2000, TimeUnit.MILLISECONDS))
{
setTimedOutWhilstReading(true);
}
}
setTimedOutWhilstWaitingForResponse(true);
}
}
catch(InterruptedException e) {
} finally {
lock.unlock();
}
then in Parser I have
this...
....
....
public Parser(final Condition condition)
{
this.condition = condition;
}
public void
run() {
try {
synchronized(this)
{
wait(10000);
// <--------- simulate this parser taking 10 seconds reading, causing timeout
in calling thread
}
} catch (InterruptedException e) {
}
try
{
condition.signal();
} catch(IllegalMonitorStateException
e) {
}
}
Okay, let me try and
explain:
I have a thread (X) that creates a parser (Y). X has to check
for a few things,
namely that Y hasn't timed out waiting for a response (the
first await in X) then
if it has timed out X checks to see if Y has started
to parse a response. I've
simulated in Y that Y takes 10 seconds to do it's
business (ignorning a
response read etc..I'm just interested in overall time
at this point).
Now, in X, because the two awaits have timed out (total
~4 seconds), X has
moved on and exited out of it's run() and the calling
thread of X does some
extra things...etc...
But, because X has moved
on, when I call condition.signal() I have to catch
an
IllegalMonitorStateException! This seems to me a bit "strange." I can
perhaps
hazzard a guess that because the lock (it's condition) in X no longer
exists, then
calling condition.signal() in Y causes this, but my question is
- is this correct? Do
I have to do this? Am I not tripping out?
Now,
the reason I have condition.signal() is that in the version of Parser that
does the parsing and returns in < 4 seconds, then X which is sitting in
an
await state, calling condition.signal() is the right thing to do - I have
to tell X
that Y is finished....
What I'm trying to understand is what
happens if Y takes a long long time, what
I have to do to X (and Y) for the
states to be properly managed....
I hope this is clear? If not, then
please do ask me for clarification...
Thanks so so much, and I look
forward to participating in this list!
-=david=-