img
.
Obviously, this kind of design is not possible using Java's synchronized sections. You could
extend our Mutex class to behave like this, but the overhead is so large that it is very unlikely to
be worth the effort.
Race Conditions
Races are instances of indeterminacy in otherwise deterministic programs. The result a program
will give in a race condition depends upon the luck of the draw--which thread happens to run first,
which LWP happens to get kicked off its processor by the page daemon, etc. Race conditions are
generally bad things, although there are times when they are acceptable. Certainly, one would be
upset if 1414.60/2.414 came out to be 586 on one run of a program and 586.001 on the next.
Most commonly, race conditions come around in programs in which the programmer forgot to
write proper locking protection around some shared data or when locks were taken out of order.
Still, it is certainly possible to write code that is perfectly correct, yet suffers from races. Consider
Code Example 7-9; if v starts with the value one, the result will either be one or zero, depending
upon which thread runs first.
Example 7-9 Simplistic Race Condition
Thread 1
Thread 2
synchronized (one) {
synchronized (one) {
v = v - 1;
v = v * 2;
}
}
It is worth noting that some instances of indeterminacy in a program are acceptable. If you write a
program that searches for a solution to a chess problem by creating lots of threads to consider lots
of different possible moves, you may get different answers depending upon which thread
completes first. As long as you get one good answer ("Checkmate in three!"), you don't really care
if you move your pawn or your rook first.
Recovering from Deadlocks
A common question is, "What if a thread that is holding a lock dies? How can I recover from
this?" The first answer is, "You can't." If a thread was holding a lock, it could legitimately have
changed portions of the data that the lock protected in ways impossible to repair. If it was in the
midst of changing the balance of your bank account, there is no inherent way for you to know
whether or not it had credited the deposit it was working on. This is, of course, a very bad thing.
Pthreads makes no provision for this situation. Only the owner of a mutex can release it, and
should that owner die, the mutex will never be released. Period. This is not really a problem for
well-written programs. The only way for a thread to die is for the programmer to write the code
that kills it. Thus, the proper answer here is, "Fix your code!"
You can, however, build arbitrarily complex "recoverable" locks from the primitives in all the
libraries. Using them properly is the trick. Win32 and UI robust mutexes do allow recovery should
the owner thread die. This is nice functionality if you need it, but it makes mutexes more
expensive to use when you don't.
In a single-process, multithreaded program, recovering from deadlocks is not too much of an issue.
You have complete control over your threads, and if your process dies, all the threads die with it.
In a shared memory, multiple-process program, it is more problematic, as it is possible for one
process to die while leaving others running.
Search WWH :
Custom Search
Previous Page
Multithreaded Programming with JAVA - Topic Index
Next Page
Multithreaded Programming with JAVA - Bookmarks
Home