|
|
|
Advertisement
|
Throwing a concurrent wrench into the works
Unfortunately, this happy picture of a well-behaved
RGBColor object can turn scary when other threads enter
the picture. In a multithreaded environment, instances of the
RGBColor class defined above are susceptible to two kinds
of bad behavior: write/write conflicts and read/write conflicts.
Write/write conflicts
Imagine you have two threads, one thread named "red" and another named
"blue." Both threads are trying to set the color of the same
RGBColor object: The red thread is trying to set the color
to red; the blue thread is trying to set the color to blue.
Both of these threads are trying to write to the same object's instance variables concurrently. If the thread scheduler interleaves these two threads in just the right way, the two threads will inadvertently interfere with each other, yielding a write/write conflict. In the process, the two threads will corrupt the object's state.
The Unsynchronized RGBColor applet
The following applet, named Unsynchronized RGBColor,
demonstrates one sequence of events that could result in a corrupt
RGBColor object. The red thread is innocently trying to
set the color to red while the blue thread is innocently trying to set
the color to blue. In the end, the RGBColor object
represents neither red nor blue but the unsettling color, magenta.
To step through the sequence of events that lead to a corrupted
RGBColor object, press the applet's Step button. Press
Back to back up a step, and Reset to back up to the beginning. As you
go, a line of text at the bottom of the applet will explain what's
happening during each step.
For those of you who can't run the applet, here's a table that shows the sequence of events demonstrated by the applet:
| Thread | Statement | r | g | b | Color |
| none | object represents green | 0 | 255 | 0 | |
| blue | blue thread invokes setColor(0, 0, 255) | 0 | 255 | 0 | |
| blue | checkRGBVals(0, 0, 255); |
0 | 255 | 0 | |
| blue | this.r = 0; |
0 | 255 | 0 | |
| blue | this.g = 0; |
0 | 255 | 0 | |
| blue | blue gets preempted | 0 | 0 | 0 | |
| red | red thread invokes setColor(255, 0, 0) | 0 | 0 | 0 | |
| red | checkRGBVals(255, 0, 0); |
0 | 0 | 0 | |
| red | this.r = 255; |
0 | 0 | 0 | |
| red | this.g = 0; |
255 | 0 | 0 | |
| red | this.b = 0; |
255 | 0 | 0 | |
| red | red thread returns | 255 | 0 | 0 | |
| blue | later, blue thread continues | 255 | 0 | 0 | |
| blue | this.b = 255 |
255 | 0 | 0 | |
| blue | blue thread returns | 255 | 0 | 255 | |
| none | object represents magenta | 255 | 0 | 255 |
As you can see from this applet and table, the RGBColor
is corrupted because the thread scheduler interrupts the blue thread
while the object is still in a temporarily invalid state. When the red
thread comes in and paints the object red, the blue thread is only
partially finished painting the object blue. When the blue thread
returns to finish the job, it inadvertently corrupts the object.
|
Sponsored Links
|