Hi David,
I appreciate your email back tremendously, it helps to clarify what I'm trying to do :-) The thing
is, I am waiting for a state to happen. The first thread X should wait (for a certain amount of time)
until thread Y has done it's job. If Y continues for too long, X should continue and Y should be
abandoned, otherwise Y will return in time and X can process the results.
I believe this is a good model for Lock, newCondition and await(with timeout) and signal and
after the helpful comments back, I'm now passing in the lock as well as the condition into
thread Y, which then calls await on the condition, after reacquiring the lock. Doing it this way
I now do not get any exceptions.
Does this feel right to you?
btw, and this is a shout out to all those who have contributed to Java Concurrency in
Practice - what an excellent booK!!!!!! :-)
-=david=-
On 10/24/06, David Holmes <dcholmes@xxxxxxxxxxxxxxx> wrote:
David,
You are misusing await()/signal(). The whole point of
Conditions is to wait for some state to be achieved. Hence you should acquire
the lock and while the state is not what you expect, perform the await(). The
thread that is updating the state will acquire the same lock, update the state
and perform the signal()/signalAll(). You can abstract out the state changes if
the "change" is actually just "event X occurred" - in which case a Semaphore or
CountDownLatch might be suitable as a coordination
mechanism.
Sorry this is a rushed reply and I don't have the
cycles right now to fully understand what you are trying to
do.
Cheers,
David Holmes
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=-
This e-mail is bound by the terms and conditions described at
http://www.subexazure.com/mail-disclaimer.html
_______________________________________________
Concurrency-interest mailing list
Concurrency-interest@xxxxxxxxxxxxxxxxxxxx
http://altair.cs.oswego.edu/mailman/listinfo/concurrency-interest
_______________________________________________
Concurrency-interest mailing list
Concurrency-interest@xxxxxxxxxxxxxxxxxxxx
http://altair.cs.oswego.edu/mailman/listinfo/concurrency-interest
|