img
. . .
You see, in this design, both consumers and producers will be sleeping on the same synchronized
object. It would be unfortunate should a consumer take an item off the list and wake up another
consumer instead of a producer, as intended.[14] With the right combination of list lengths, and
number of producers and consumers, this code is likely to be inefficient, and it is even possible
that it will deadlock.
[14]
This is not an obvious situation and requires some careful analysis to figure out. Moreover, it is
possible that this program will work well on one platform while hanging on another. Part of the logic
here relies on the order of wakeup for sleeping threads, something that is not guaranteed by the
JVM. This, by the way, is a good thing, as the programmer should never rely on wakeup order.
The solution is simple: Consumers should only wake up producers, and producers should only
wake up consumers. Unfortunately, the Java method notify() is linked specifically to the
synchronized object, so there's no way to direct wakeups as we'd like. We could wake up
everybody by calling notifyAll(). That would definitely give us a correctly working program,
but it could[15] be abysmally inefficient. Let's consider a POSIX-style alternative.
[15]
Would it be abysmally inefficient? We'll take up this issue in Condition Variables vs. wait/ notify .
POSIX-Style Synchronization in Java
What we're going to do is implement POSIX-style mutexes and condition variables in Java.
Because POSIX mutexes and condition variables are separate, independent objects, it is possible
to construct exactly the program logic that we really want. First, let's look at the classic POSIX
solution to this problem, shown in Code Example 6-18.
Example 6-18 Classic Producer/Consumer in POSIX
void *producer(void *arg) {
request_t *request;
while(1) {
request = get_request();
pthread_mutex_lock(&requests_lock);
while (length >= 10)
pthread_cond_wait(&producerCV, &requests_lock);
add_request(request);
length++;
pthread_mutex_unlock(&requests_lock);
pthread_cond_signal(&consumerCV);
}
}
void *consumer(void *arg) {
request_t *request;
while(1) {
pthread_mutex_lock(&requests_lock);
while (length == 0)
pthread_cond_wait(&consumerCV, &requests_lock);
request = remove_request();
length--;
pthread_mutex_unlock(&requests_lock);
pthread_cond_signal(&producerCV);
Search WWH :
Custom Search
Previous Page
Multithreaded Programming with JAVA - Topic Index
Next Page
Multithreaded Programming with JAVA - Bookmarks
Home