Java Threading Model Issues

Tom Cargill

Profile Consulting, Inc.

Introduction

The purpose of this note is to identify some parts of the specification of the Java threading model that are incomplete or inconsistent. The goal in identifying these flaws is to assist in the preparation of an improved specification. The absence of a clear specification is hindering the serious use of Java.

The Specification

The current specification of the Java threading model is in the Java Language Specification (JLS), as augmented and modified at the Javasoft web site.

The Thread.interrupt() Method

The specification of Thread.interrupt() and related methods are unclear in several respects.

First, from inspection of the source code of JDK1.1 and 1.2, it appears that Thread.isInterrupted() and Thread.interrupted() differ, in that the latter clears the interrupt request flag. This distinction appears nowhere in the documentation. What is the intent? Several different specifications would be consistent with the current JSK implementations. For example, one method must clear the flag while the other must not, both methods may clear the flag, etc. Inferring the specification from a particular implementation is risky at best. That practice has misled both programmers and authors with respect to Java's threads.

Second, on Solaris JDK1.2, java.net.ServerSocket.accept() throws java.io.InterruptedIOException when interrupted by Thread.interrupt(). However, the same exception is used by that method to signal a time-out. What is the intent? Is there to be a consistent mechanism for interrupted I/O, or will every method be coded arbitrarily? Should the programmer be able to detect unambiguously that an interrupt has occurred? More generally, is a core library method obliged to react to interruption at all, or may an interrupted thread block in the standard library?

Third, if a thread is waiting in Object.wait(), and is both signaled by Object.notify[All]() and interrupted by Thread.interrupt(), what happens? Is the model affected by the order of notification versus interruption in any way? If the interruption always dominates the notification, is the notification lost, or must the run-time redirect the notification to another thread that is waiting for notification on that lock? May the run-time do so? (Optional redirection of notification may be subsumed by the next issue.)

Spurious Notification

It is rumored (for example, as discussed at a recent birds-of-a-feather session at COOTS98) that Java may be changed to permit "spurious notification." That is, a thread that is waiting in Object.wait() may resume execution, as if it had been notified, even if no notify[All]() has been issued on that lock. Is this rumor well-founded? Such a change would affect the use of techniques that rely on directing notification to specific threads, by requiring the application code to maintain additional state that records which notifications have been issued.

This paper argues neither for nor against spurious notification, but only for clarification of the issue. Pragmatically, if the implementation costs of avoiding spurious notification are prohibitively high, so be it. Other parts of the threading model are specified weakly in order to reduce implementation costs.

The Deprecation of stop()

In JDK1.2, the methods Thread.stop(), Thread.stop(Throwable), Thread.suspend() and Thread.resume() are deprecated. The underlying motivation for this step appears reasonable: casual use of these methods can easily destroy the overall integrity of a concurrent system.

However, Javasoft's suggested alternatives to using stop() etc. is deficient. In particular, its first example of an alternative to stop() is:

public void stop() {
  blinker = null;
}

public void run() {
  Thread thisThread = Thread.currentThread();
  while (blinker == thisThread) {
    try {
      thisThread.sleep(interval);
    } catch (InterruptedException e){
    }
    repaint();
  }
}
See the suggested alternatives for the context that explains this code. The code is well-intentioned, but does not work in general, as shown. It does not work because the applet's stop() method, which sets blinker to null, does nothing to force that value to be written back to main memory, where it can then be accessed by the thread to be stopped. The value can remain cached in the stopping thread's working memory for an arbitrary time. An essential part of this approach is that either the field used for inter-thread signaling be declared volatile or that such access to it be wrapped by lock synchronization.

The motivation for this paper is to draw attention to the lack of documentation from Javasoft on the state and direction of the threading model. In this case, it is frustrating that a supporting document exhibits insufficient attention to detail. Alternatively, the code above may be correct, because of as yet undocumented changes to the threading model. If so, what are those changes?

Another nominal alternative to Thread.stop() is the Thread.destroy() method. Although destroy() has been present since Java's initial release, it has never been implemented. Given that destroy() is as "dangerous" as stop(), why has it not also been deprecated? Will it be specified and implemented eventually? There are (rare) circumstances in which a mechanism for unilateral thread termination is legitimate; if destroy() is part of the model, it addresses that (minority) need.

If neither stop() nor destroy() are to be available, all thread cancellation in Java must depend on some degree of cooperation from the thread to be terminated. Requiring such cooperation constrains the nature of the systems that can be built. (Such a constraint would not be unreasonable; Java's lack of hard real-time mechanisms is not unreasonable.) What is the intent?

Moving Forward

The goal of this note is to draw attention to the lack of detail in the specification of the Java threading model, in the hope that it can be improved. Comments, corrections and suggestions are welcome by email to the author. Specific, constructive suggestions on how to persuade Javasoft to improve the quality of the specification are particularly solicited.

Acknowledgments

My thanks to Doug Lea, David Holmes and Bil Lewis for various insights into these matters.

tac 5/6/98