The fundamental operation is quite simple: You call the cancellation function with the target
thread, and the target thread dies sometime "soon." The ramifications of doing this are, however,
quite complex, making cancellation one of the most difficult operations to execute correctly.
Polling for Cancellation
There are three basic techniques of cancelling threads. The simplest is to do it ad hoc. You set a
flag and let all the target threads continue to run until they see it. This is what we did in our
StopQueue example. This is great unless one of your threads is blocked waiting for I/O, in which
case it may never notice that the flag has been set.
The second method is known as asynchronous cancellation. This is what most people think of first.
You call the cancel function and the target thread dies "soon." If the thread is sleeping or
blocked on I/O, it will be awakened in order to die.
The actual delivery time of a stop request is not specified. The most obvious implementation for a
truly asynchronous stop is to use UNIX signals or NT's equivalent. Signals in UNIX are indeed
asynchronous, but not as immediate as you might imagine. The usual implementation of signals is
for the caller to mark a bit in the target's process structure, and for the caller to look at that bit only
when context switching on the system clock. Thus delivery of signals, hence stop notifications,
occurs only at clock ticks. Perfectly legal but not intuitive.
This is the only type of cancellation that Win32 provides. You call TerminateThread() and
the target thread dies. Unfortunately, should that thread own some resource, hold some lock, or
have malloced some memory, your program will be in trouble. This type of cancellation is known
as unrestricted asynchronous cancellation, and it is the responsibility of the killer to know that the
victim can be safely eliminated at the time of cancellation--a difficult task at best, impossible at
In POSIX you get this behavior by calling pthread_cancel() with the cancellation type set to
asynchronous. In Java, the method thread.stop() behaves similarly, save that any
synchronized sections will be released and any finally clauses will be executed.
The third type of cancellation is known as deferred cancellation. In this type of cancellation, a
thread exits only when it polls the library explicitly to find out if it should exit. When the thread
blocks in a library call which is a cancellation point [e.g., sem_wait()], the thread will be
awakened in order to exit. POSIX defines a set of standard library functions that must call it (see
In POSIX, there's a function pthread_testcancel(), which checks to see if a bit has been
set. If the bit is set, it exits the thread; otherwise, it returns, and the thread continues normally.
Using interrupt() for Deferred Cancellation
In Java, InterruptedException and InterruptedIOException are used in much the
same fashion as POSIX deferred cancellation. One thread may call interrupt() on another
thread, and when that thread hits an interruptible point (the Java analogue to POSIX cancellation
points), that method will then throw an InterruptedException or
InterruptedIOException, and you may then handle that exception as you see fit. If your
objective is to kill the thread, you may simply have the exception handler exit the thread. If you
Search WWH :