|
|
Re: Await...Signal -CatchingIllegalMonitorStateException???: msg#00051
java.jsr.166-concurrency
|
Subject: |
Re: Await...Signal -CatchingIllegalMonitorStateException??? |
Correction - acquiring the Lock before the signal will ensure that the
main thread has called await() first. See - rushing too
much.
David
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
| |