Start of Tutorial > Start of Trail > Start of Lesson |
Search
Feedback Form |
In this example, theProducer
generates an integer between 0 and 9 (inclusive), stores it in aCubbyHole
object. To make the synchronization problem more interesting, theProducer
sleeps for a random amount of time between 0 and 100 milliseconds before repeating the number-generating cycle:Thepublic class Producer extends Thread { private CubbyHole cubbyhole; private int number; public Producer(CubbyHole c, int number) { cubbyhole = c; this.number = number; } public void run() { for (int i = 0; i < 10; i++) { cubbyhole.put(number, i); try { sleep((int)(Math.random() * 100)); } catch (InterruptedException e) { } } } }Consumer
consumes all integers from theCubbyHole
(the exact same object into which theProducer
put the integers in the first place) as quickly as they become available.public class Consumer extends Thread { private CubbyHole cubbyhole; private int number; public Consumer(CubbyHole c, int number) { cubbyhole = c; this.number = number; } public void run() { int value = 0; for (int i = 0; i < 10; i++) { value = cubbyhole.get(number); } } }Producer
andConsumer
example share data through a commonCubbyHole
object. AlthoughConsumer
ideally will get each value produced once and only once, neitherProducer
norConsumer
makes any effort whatsoever to ensure that happens. The synchronization between these two threads occurs at a lower level, within theget
andput
methods of theCubbyHole
object. However, assume for a moment that these two threads make no arrangements for synchronization, and let’s discuss the potential problems that might arise from this.One problem arises when the
Producer
is quicker than theConsumer
and generates two numbers before theConsumer
has a chance to consume the first one. In this situation, theConsumer
misses a number. Part of the output might look like this:Another problem might arise when the Consumer
is quicker than theProducer
and consumes the same value twice. In this situation, theConsumer
might produce output that looks like this:Either way, the result is wrong because the Consumer
should get each integer produced by theProducer
exactly once. A problem such as this is called a race condition. A race condition is a situation in which two or more threads or processes are reading or writing some shared data, and the final result depends on the timing of how the threads are scheduled. Race conditions can lead to unpredictable results and subtle program bugs. Race conditions in the producer-consumer example are prevented by having the storage of a new integer into theCubbyHole
by theProducer
be synchronized with the retrieval of an integer from theCubbyHole
by theConsumer
. The activities of the Producer and theConsumer
must be synchronized in two ways.First, the two threads must not simultaneously access the
CubbyHole
. A thread can prevent this from happening by locking an object. When an object is locked by one thread and another thread tries to call a synchronized method on the same object, the second thread will block until the object is unlocked.Second, the two threads must do some simple coordination. That is, the
Producer
must have a way to indicate to theConsumer
that the value is ready, and theConsumer
must have a way to indicate that the value has been retrieved. TheObject
class provides a collection of methods wait
,notify
, andnotifyAll
to help threads wait for a condition and notify other threads when that condition changes.
Start of Tutorial > Start of Trail > Start of Lesson |
Search
Feedback Form |
Copyright 1995-2005 Sun Microsystems, Inc. All rights reserved.