Recommended: Sing it, brah! 5 fabulous songs for developers
JW's Top 5
Optimize with a SATA RAID Storage Solution
Range of capacities as low as $1250 per TB. Ideal if you currently rely on servers/disks/JBODs
Page 4 of 7
The first rule to follow when making a class thread-safe through synchronizing its critical sections, therefore, is to make its fields private. Any field that you need to coordinate multithreaded access to must be private, otherwise it may be possible for other classes and objects to ignore your critical sections and access the fields directly.
Not every field must be private -- only those that will be involved in any temporarily invalid states created by the object's or class's critical sections. For example, constants (static final variables) can't be corrupted by multiple threads, so they needn't be private.
Step 2: Identify and synchronize critical sections
Once you've made the appropriate variables private, you need only mark the object's critical sections as synchronized. As
mentioned above, a critical sectionis a bit of code that must be executed atomically, that is, as a single, indivisible operation. For example, the statements:
this.r = r; this.g = g; this.b = b;
must operate atomically for the setColor() method to behave as expected in a multithreaded environment. To ensure proper behavior, these three statements need to appear
as if they were executed by a single, indivisible JVM instruction.
Note that reads and writes of primitive types and object references are atomic by definition, except for longs and doubles. This means that if you have an int, for example, that is independent of any other fields in an object, you needn't synchronize code that accesses that field.
If two threads were to attempt to write two different values to the int concurrently, the resulting value would be one or the other. The int would never end up with a corrupted value made up of some bits written by one thread and other bits written by the other
thread.
The same is not necessarily true, however, for longs and doubles. If two different threads were to attempt to write two different values to a long concurrently, you might just end up with a corrupted value consisting of some bits written by one thread and other bits written
by the other thread. Multithreaded access to longs and doubles, therefore, should always be synchronized.
RGBColor # 2: Thread safety through synchronization
Here's a revised version of the RGBColor() class. This version, which has its critical sections marked as synchronized, is thread-safe:
// In file threads/ex2/RGBColor.java
// Instances of this class are thread-safe.
public class RGBColor {
private int r;
private int g;
private int b;
public RGBColor(int r, int g, int b) {
checkRGBVals(r, g, b);
this.r = r;
this.g = g;
this.b = b;
}
public void setColor(int r, int g, int b) {
checkRGBVals(r, g, b);
synchronized (this) {
this.r = r;
this.g = g;
this.b = b;
}
}
/**
* returns color in an array of three ints: R, G, and B
*/
public int[] getColor() {
int[] retVal = new int[3];
synchronized (this) {
retVal[0] = r;
retVal[1] = g;
retVal[2] = b;
}
return retVal;
}
public synchronized void invert() {
r = 255 - r;
g = 255 - g;
b = 255 - b;
}
private static void checkRGBVals(int r, int g, int b) {
if (r < 0 || r > 255 || g < 0 || g > 255 ||
b < 0 || b > 255) {
throw new IllegalArgumentException();
}
}
}
The Synchronized RGBColor applet
The following applet, named Synchronized RGBColor, demonstrates a similar sequence of events to the one that led to a corrupt RGBColor object in the previous demonstration applet. This applet, however, shows how the thread-safe version of RGBColor is able to maintain a valid state, even when multiple threads are attempting to write to the object. As before, a red thread
is trying to set the color to red while a blue thread is trying to set the color to blue. In the end, this RGBColor object represents not the invalid color magenta, but the valid -- and satisfying -- color red.
JVMSimulator and Method.java and search for sychronized. http://www.artima.com/insidejvm/applets/sourcecode.html