|
|
Re: Await...Signal - CatchingIllegalMonitorStateException???: msg#00050
java.jsr.166-concurrency
|
Subject: |
Re: Await...Signal - CatchingIllegalMonitorStateException??? |
Hi David,
What you don't do is actually check any state before the await(). Your
code will not work correctly unless the parser thread has to acquire the Lock
before it commences parsing - otherwise it could complete the parsing and do the
signal prior to the main thread doing the await().
Passing a Lock+Condition is working at the wrong level of abstraction -
those should be encapsulated together with the state that is being
checked.
It seems like what you might have here is a use for FutureTask. Your main
thread will create the FutureTask and do a timed get() to wait for the result.
You pass the FutureTask to your parseThread and it does the actual parsing and
upon completion marks the Future task as done.
Again this is a rushed response - sorry.
Thanks for the comments re JCiP :-)
Cheers,
David Holmes
-----Original Message----- From:
concurrency-interest-bounces@xxxxxxxxxxxxx
[mailto:concurrency-interest-bounces@xxxxxxxxxxxxx]On Behalf Of David
Harrigan Sent: Wednesday, 25 October 2006 4:37 AM To:
dholmes@xxxxxxxx Cc:
concurrency-interest@xxxxxxxxxxxxx Subject: Re: [concurrency-interest]
Await...Signal - CatchingIllegalMonitorStateException???
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
| |