img
. .
It is illegal for a thread to hold a pointer to an element unless it holds the appropriate mutex. In
this case, the appropriate mutex is local, so numerous threads may hold pointers to different
elements. Note that the mutex in Jan's structure protects the "next" pointer and the following
structure (Kim's).
To update Kim's salary, a thread will need to hold the mutex in Jan's structure, not the one in
Kim's. To remove Kim from the list, once again the thread must hold the mutex in Jan's structure.
As soon as it has been removed from the list, Jan's mutex may be released. It will be impossible
for any other thread to get a pointer to Kim.
Let's look at the searching routine (used by both liquidators and raisers; Code Example 12-6). The
basic loop is simple: Look at each element, compare the name strings, return the previous pointer
if found. What is interesting about this function is the order in which locks are acquired and
released.
Example 12-6 Searching Code (ListLocalLock.java)
public static Person findPerson(Person p, Person people) {
Person previous;
people.mutex.lock();
while (people.next != null) {
if (p.name.equals(people.next.name))
return people;
// Previous person (holding
lock!)
people.next.mutex.lock();
previous = people;
people = people.next;
previous.mutex.unlock();
}
people.mutex.unlock();
return null;
}
First we lock the global lock and compare our name to the first element (Jan). If this isn't it, we
lock Jan's lock, release the global lock, and compare again. The locking/unlocking is being done in
an overlapping fashion! (It's often called chain locking.) This makes it somewhat challenging to
ensure that the correct locks are locked and unlocked in the correct order in all the different
functions.
Two Local Locks
A superior version of the local lock design may be had by providing two local locks, one to
protect the element and one to protect the salary. Now we have the advantage of allowing multiple
liquidator threads to search down the list while not causing bottlenecks. The only points of
contention occur when two threads wish to operate on the same element. There's nothing we can
do about that.
That's the good news. The bad news is that it takes time to lock mutexes. It may well take more
time to lock and unlock each mutex than it takes to do the comparison! In this code, it does. This
version of the program, shown in Figure 12-9, is significantly slower than the RWlock version.
Only if the list were short and the time to execute a comparison were long would this design give
superior results.
Figure 12-9. Friends/Enemies: Two Local Locks
Search WWH :
Custom Search
Previous Page
Multithreaded Programming with JAVA - Topic Index
Next Page
Multithreaded Programming with JAVA - Bookmarks
Home