>My view is that whatever the VM does to ensure no lost notification,
>shouldn't produce any observable change in behaviour that would not
>have been observable (as per the spec) if the notification had been
>received by an alternate thread in the first place. Notwithstanding
>any scheduling order differences that no program should be relying
Ok. We agree on that.
However, we have seen that wait/notify/interrupt is an area where the
implementations have not always conformed to the specification, even though
it appears that they could have. In most areas of IT I think one would
simply consider the implementations to be broken, and fix them. In this
particular corner, the view seems to be that we change the specification on
the grounds that it's easier, and existing programs have lived with
implementations that didn't conform to the old specification.
I still have misgivings about the validity of that argument, but at least
lets make sure the practice ends here. With this in mind, I've included the
following code that I think illustrates a non-obvious interaction between
notification propagation and thread scheduling. Expert VM implementors can
obviously ignore it as trivial.
public class Test39
static volatile Test39 m;
static volatile int waitCount = 0;
static volatile boolean thread1Woken = false;
static volatile boolean thread2Woken = false;
public static void main(String args)
m = new Test39();
// Start a couple of threads.
Thread t1 = new TestThread(1);
// Wait until both threads are in the wait() method.
while(waitCount < 2)
// Notify the monitor. This must wake up either thread 1 or
// thread 2.
// Start thread 3.
// Thread 3 may have now reached its wait call.
// Interrupt thread 1. If thread 1 was woken up above, but will
// Exception as a result of this call, then thread 2 must be woken
up - not
// thread 3!
// So this loop is guaranteed to terminate.
while(!thread1Woken && !thread2Woken)
System.err.println("main method terminating.");
static class TestThread extends Thread
private final int id;
this.id = id;
public void run()
System.err.println("Thread " + id + " running.");
System.err.println("Thread " + id + " woke up;
interrupted = " + Thread.interrupted());
if(id == 1)
thread1Woken = true;
else if(id == 2)
thread2Woken = true;
catch (InterruptedException ex)
System.err.println("Thread " + id + " interrupted.");
The issue here is that an implementation that propagates a notification at
the point where Thread.interrupt() is called, or at any later time, risks
waking up thread 3 rather than thread 2. If that happens, then thread 1 is
interrupted, thread 3 is woken up, but thread 2 is left waiting. This
combination of events is not permitted by the specification even where
wait() is allowed to wake up spontaneously.
One solution is to ensure that threads are woken up in the order in which
they wait, but I can't say whether there's another correct program that
It's this sort of scenario that makes me uncomfortable about fudges that
provide supposedly logically equivalent behaviours. It's too easy to get it
wrong, and the fact that the existing implementations don't work correctly
gives me no confidence that the VM writers will really provide correct
implementations. Then we'll come back in a few years, and tweak the
JavaMemoryModel mailing list - http://www.cs.umd.edu/~pugh/java/memoryModel
This archive was generated by hypermail 2b29 : Thu Oct 13 2005 - 07:00:45 EDT