Re: JavaMemoryModel: Proposals on wait and interrupts

From: Miles Sabin (miles@milessabin.com)
Date: Tue May 27 2003 - 04:19:28 EDT


Sylvia Else wrote,
> Proposal 3: On entry, the wait call atomically throws IE if the
> interrupted flag is _already_ set, and otherwise enters the wait
> state. Once the wait state is entered, not even interrupting the
> thread can make the method throw IE. Instead, interrupting the thread
> merely wakes it, and leaves it with its interrupted flag set.

This seems to be the behaviour of the 1999 era hotspot described in the
first of the bug reports David just mentioned,

  http://developer.java.sun.com/developer/bugParade/bugs/4265374.html

As it happens, the reporter was me, and I recall that Doug and I had a
longish exchange about this behaviour at the time (Doug pointed out
that the behaviour was within spec, but that it was maybe a little
unfortunate and hoped the JLS would be tweaked to prefer an IE throw
"soon" ;-)

FWIW, as a "working programmer" I don't consider the behaviour to be a
bug any more, and I'd now mildly prefer notification to be given
preference over interruption (IOW, I support Sylvia's proposal 3). When
I made that report I hadn't fully appreciated the impact of spurious
wakeups and interruptions, and in fact the concrete design which
prompted it was completely broken.

The conclusion I came to later was that interruption was inadequate for
reliable handling of cancellation because a thread's interrupt status
can be modified unpredictably, eg. _any_ holder of a reference to the
thread running the cancellable activity can set or clear the thread's
interrupt status irrespective of any behavioural encapsulation
boundaries. This is unfortunate in applications which mix code from a
variety of sources (which is almost all of them) ... I can know how I
use and respond to interrupts in my code, but not what happens
elsewhere.

As a result I took to making cancellation a first-class aspect of
cancellable activities, and to all intents and purposes ignore
InterruptedExceptions completely, eg.,

  public class CancellableActivity
    extends Thread
  {
    private final Object lock = new Object();
    private boolean cancelled = false;
    
    public void cancel()
    {
      synchronized(lock)
      {
        cancelled = true;
        lock.notify();
      }
    }

    public void run()
    {
      synchronized(lock)
      {
        while(!condition())
        {
          try
          {
            lock.wait();
          }
          catch(InterruptedException ex)
          {
            // Deliberately ignored ... cancellation attempts
            // which respect behavioural encapsulation will
            // invoke cancel() rather than using interruption
          }

          if(cancelled)
          {
            // respond to cancellation

            return;
          }
        }

        // respond to notification
      }
    }

    private boolean condition() { ... }
  }

This is pretty clearly replicating the functionality of Thread.interrupt
and Thread.isInterrupted, but is doing so in a way which wouldn't be
made redundant by making the throwing of InterruptedExceptions more
reliable and/or preferred over notifications, because in this design
arbitrary code elsewhere in the application can't mess up the semantics
by obtaining a thread reference somehow and arbitrarily twiddling its
interrupt status.

Actually, I guess there's a Proposal 4 lurking in here somewhere,

  Redefine Thread.interrupt as a NOP and isInterrupted to return false
  always. Deprecate both these methods. Encourage developers to expose
  an explicit cancellation interface to activities which should be
  cancellable.

Only kidding ;-)

Cheers,

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