Hi,
On Wed, May 31, 2000 at 10:43:00AM +0200, Jochen Hoenicke wrote:
> > I did have a strange problem with java.util.Timer with gcj. Sometimes I
> > would get java.lang.IllegalMonitorStateException when testing it.
> > Could someone with a newer or cvs version of gcj (I have 2.95.2) try the
> > attached program with the java.util.Timer[Task] classes from cvs
> > (you have to compile them with jikes first to get class files)
> > and tell if you still get a IllegalMonitorException. I hope it is a bug
> > in gcj, but it might also very well be a bug in my code.
>
> I had a looked through these classes, to see if this is caused by an
> obvious bug, but all notify() and wait() calls are synchronized as
> they should. The classes look good, great work!
Yes. That is what I though. So I suspect that it is a bug in gcj but since
gcj doesn't seem to to implement Throwable.printStackTrace() I cannot find
where this is happening.
> But I think there is a race in Scheduler.run(). IMHO the queue
> monitor must be kept between queue.top() and queue.sleep(). Otherwise
> a task may be enqueued in between and the scheduler wouldn't notice
> since the notify() comes before the sleep().
Good catch. Now that you have pointed it out it seems so obvious.
But I always wondered what a good method is to prevent or prove these
kinds of race conditions. (You say IMHO, is that because you want to be
friendly or because you cannot express the proof without any doubt?)
I will change the parameter to the sleep method so it represents the top
TimerTask in the queue that you want to sleep on. Then sleep can check if
the top task has changed and return immediatly if it has changed and do
the real sleep otherwise (which should solve the race since sleep is
synchronized).
> I also think notifyAll() is "more correct" than notify(), but that
> doesn't really matter, since the scheduler is the only one that may be
> waiting.
I will add a comment to the sleep/interrupt methods that only the scheduler
is should call these methods.
Thanks,
Mark