[concurrency-interest] Re: interrupt / notify races even in 6.0beta?

David Holmes dcholmes at optusnet.com.au
Sun May 21 17:34:23 EDT 2006


> Dawid Kurzyniec wrote:
> I realize that you (EG) have dealt with this issue for decades now; so
> please have a little patience with me here; I'd like to understand the
> problem fully to make sure that I don't screw up anything in the
> backport. It is no mystery that there is a possible race between notify
> / interrupt, as it is between memory read / write, when there is no
> happens-before relationship between these operations. Ideally, and
> intuitively however, I would expect that the ordering of notify /
> interrupt becomes deterministic when there is a happens-before
> relationship, e.g. if the operations are invoked from the same thread.
> Apparently, it is not the case, and the spec does not actually promise
> it. I am trying to understand why it can't be made to be the case. For
> instance, why can't the interruption status be combined with a thread
> state (runnable, blocked, waiting, io) into an atomic state variable -
> having interrupt() CAS-ing it to INTERRUPTED, removing the tread from
> the condition's wait set if was WAITING, and having notify() loop
> CAS-ing the state of a candidate thread to RUNNABLE if was WAITING, and
> skipping it over if was INTERRUPTED. Perhaps the problem is that the OS
> layer does not expose things this way?...

I fully sympathise with you as I was in the exact same position asking the
exact same questions and wanting similar answers. Since then I have learned
the "why" of it.

Anything is possible, and a design as outlined above is possible, but that
isn't the way hotspot evolved in this area. In simple terms there are two
things going on here:

1. interrupt() is only loosely coupled to the use of monitors. interrupt()
ensures that a blocked thread wakes up but it doesn't check to see why (or
even if) the thread was blocked in the first place, and so in this case it
doesn't make any change to the wait-set. So in a sense, yes it is

2. Contrary to what Doug indicated the VM actually favours notification over
interruption (while jsr-166 stuff does the opposite).

Hence by the time the thread wakes up due to the interrupt, the main thread
has also removed it from the wait-set. The VM favours notification and so
you get a normal return with the interrupt bit set.

The OS issues are more to do with timeouts - because the OS sometimes lies
and you can't tell you timed-out. That is something else I lament - that
even with jsr-166 you can't truly tell for certain whether or not you
timed-out. :(

> But then again, with the
> low-level primitives like those used by park/unpark, wouldn't it be
> possible to implement it at the JVM side, without relying on OS-level
> wait sets etc?

If at some point in the future the same mechanism were to be used for
jsr-166 sync and monitor sync, then you would get the same (unspecified)
behaviour from each.

So any "test" that assumes the order of notifications and interrupts is
invalid. All you can test is whether the interrupt state is set or cleared
correctly, and that notifications are not lost.

If you want all the gory details sign up at java.net and download the
Mustang snapshots :)

David Holmes

More information about the Concurrency-interest mailing list