JavaMemoryModel: Proposals on wait and interrupts

From: Bill Pugh (pugh@cs.umd.edu)
Date: Mon May 26 2003 - 11:03:25 EDT


OK, to clarify the thoughts that have been floating around over the
past dozen or so messages, I think there are two concrete proposals.

Proposal 1: a thread performing a wait should prefer throwing an IE
over returning normally. In particular, if
* thread T1 calls m.wait()
* thread T2 calls T1.interrupt()
* thread T2 calls m.notify() or m.notifyAll()

Then T1 should exit the wait by throwing an IE.

Sun's current VM's fail this test (code attached at bottom).

Proposal 2: if a thread T1 performing a wait on object m is removed
from the wait set via a call to m.notify(), and T1 exits the call to
wait by throwing an IE, then the VM should ensure that another
m.notify() is performed. Since spurious returns are allowed, one
implementation of this would be to have any call to wait that throws
an IE perform a re-notification.

-------

Commentary: the proposals are completely independent, we can adopt
neither, one or the other, or both.

Sylvia didn't like the renotification rule, because it doesn't have
the same semantics as non-deterministically making sure that notified
threads and interrupted threads are disjoint. I don't think this is a
realistic expectation, and in particular, I don't the example he gave
is one that we should guarantee should work. The renotification rule
isn't trivial, but it ensures that many design patterns for using
notify() work, without requiring explicit calls by the programmer to
notify in all of the catch blocks for IE.

        Bill
-----

class InterruptTest1 implements Runnable {

   int state = 0;

   public void run () {

        try {
        synchronized(this) {
                state = 1;
                notify();
                wait();
                if (state == 2)
                        System.out.println("wait returned normally");
                else
                        System.out.println("spurious return from wait");
                System.out.println("interrupted = " + Thread.interrupted());
                }
        } catch (InterruptedException e) {
                System.out.println("Got InterruptedException");
                }
        }

   public static void main(String args[]) throws Exception {

        InterruptTest1 it = new InterruptTest1();

        Thread t = new Thread(it);

        synchronized(it) {
                t.start();
                while (it.state == 0) it.wait();
                it.state = 2;
                // Interrupt before notify, so the call to wait
                // in the run method should throw an interrupted
                // exception rather than return in an interrupted state
                System.out.println("Interrupted, then notifying");
                t.interrupt();
                it.notify();
                }
        }
}

-------------------------------
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