img
. . .
The point is that we don't want to have to catch InterruptionException all the time, and we
particularly don't want to have to write exception handlers that clean up the world all over the
place. As long as we know we have a time bound on our code, we don't want to deal with these
exceptions at all. Unfortunately, this is the way that Java works and we have to deal with them
anyway.
Obviously, there are many options here and the issues are quite complex. We have yet to see a
sufficiently complete solution to them. Our opinion is that simplicity is best. Maximal simplicity.
If we could, we would use the InterruptibleThread to disable InterruptedException
everywhere except in unbounded blocking reads. If we didn't have control over the threads, we
would use the reinterrupt technique in our libraries and require the program to unblock our waits
explicitly, as with StopQueue.
So, should our explicit Mutex class throw InterruptedException or should it catch it and
reinterrupt later? We chose the latter for exactly the same reason that POSIX and Java chose it.
With hundreds of locks scattered throughout our code, it would be a nightmare to catch exceptions
at every call. (Consider the extreme example of requiring every call to new to catch an
OutOfMemoryException!)
This is why none of our synchronization variables throw InterruptedException. The
programmer can always ensure that they don't block forever and is thus freed to deal with
InterruptedException in fewer places in the code. Fewer is better. If you really wanted to,
of course, you could write your own versions of Mutex, etc., that did throw
InterruptedException.
When should you write a method that throws InterruptedException? Probably never.[8]
[8]
This is bound to be a topic of debate, and we don't claim any special knowledge. We just haven't
seen any better suggestions.
Interrupting Sleeping Threads
A thread that is waiting for a synchronized section lock to be released is not at an interruptible
point, and it will continue to sleep until that lock is released. Once it acquires the lock, it must
proceed until it hits an interruptible point (ditto for POSIX mutexes). This can be a serious
sticking point when you are concerned about elapsed wall-clock time. Just be sure that you don't
hold any locks that the interrupted threads might need.
Interruption in wait()
While wait() is an interruption point,[9] there is an additional issue that must be addressed. Upon
a normal return, it always re-locks the synchronized section. Upon interruption, it must also re-
lock said synchronized section! Any exception handlers will be run with the lock held as
appropriate. This means that if you're interrupting a thread to kill it quickly, you'd best be sure that
no one is holding that lock for a long time.
[9]
Should wait() be an interruption point? A strong case can be made for it not being one, but in
as much as we don't have any say on the matter, we'll just accept it as is. [If a thread is blocked on
wait(), the programmer has complete control over it and can wake it up and have it see that it's
exit time, the way we did in the StopQueue example. It's only when a thread is blocked on
something that we don't have control over (e.g., I/O) that we need to be able to interrupt it.]
In Code Example 9-14 both the exception handler and the finally section will run with the lock
held. If the synchronization had been inside the try clause, the exception handler and the
Search WWH :
Custom Search
Previous Page
Multithreaded Programming with JAVA - Topic Index
Next Page
Multithreaded Programming with JAVA - Bookmarks
Home