img
. .
Case 3 assumes that you have implemented FIFO mutexes, where the owner of the mutex
automatically hands ownership over to the first waiter when releasing the mutex.
This is a rare situation, and it merits reconsidering your algorithm before dealing with it. (If you
contrast case 2 and case 3 against case 1, you will notice that the two threads are spending a lot of
time sleeping on the job. This might run better with fewer threads!) But should you find yourself
stuck with this kind of problem, it is a simple programming effort for you to implement
guaranteed FIFO mutexes yourself. Once again, you almost certainly don't want FIFO mutexes.
Recursive Mutexes
Win32 mutexes are recursive--they can be locked multiple times from the same thread without
deadlocking. POSIX mutexes cannot. Building a recursive mutex with POSIX is not at all difficult
(an excellent exercise!) and indeed recursive mutexes are part of UNIX98. The real question is not
if you can build them, but whether it's a good idea.
The chances are very high that if you have a situation where you want to use recursive mutexes in
C, you'd be better off redesigning your code so that you don't need them. Why are you locking this
mutex? To protect some shared data. Once you've done so, why would you ever want to lock it
again? Because your code is structured poorly. Fix your code.
Once you've locked a recursive mutex three times, you will need to unlock it three times before
any other thread can lock it. You could write an "unlock_all" routine, but it would probably just
make your code even more confusing and very likely lead you to make mistakes.
In Java, synchronized sections are also recursive (Code Example 7-2). One synchronized method
may call another synchronized method of the same object from the same thread without
deadlocking.[1] A call to wait() will release the lock and when wait() returns, the lock will be
reacquired at the same depth. The usual programming Java style almost makes it a requirement to
have recursive mutexes. It would probably be a better thing if people wrote code such that they
had public methods which were synchronized, which in turn simply called internal methods to do
the real work, but this is unlikely to happen. Indeed, if we had a perfect programming language,
this issue would not even come up.
[1]
Java does not actually specify that locks are recursive, merely that synchronized calls may be
made recursively. A sufficiently clever compiler could optimize most code so as to avoid actual
recursive mutexes. I don't know of any such compilers.
Example 7-2 Recursive Locking Calls in POSIX and Java
POSIX
Java
void foo(){
public synchronized void foo() {
pthread_mutex_lock(&m);
bar();
bar();
pthread_mutex_unlock(&m);
...
}
void bar() {
public synchronized void bar() {
pthread_mutex_lock(&m); // Deadlock
...
wait();
// works fine!
pthread_mutex_unlock(&m);
}
}
Nonblocking Synchronization
Search WWH :
Custom Search
Previous Page
Multithreaded Programming with JAVA - Topic Index
Next Page
Multithreaded Programming with JAVA - Bookmarks
Home