Designing for Thread Safety

Using Synchronization, Immutable Objects, and Thread-Safe Wrappers

by Bill Venners
July 15, 1998

First published in JavaWorld, July 1998
Summary
This article gives you design guidelines pertaining to thread safety. It provides a background on thread safety and shows several examples of objects that are and are not thread-safe, including two illustrative applets. In addition, the article offers guidelines to help you decide when thread safety is appropriate and how best to achieve it.

Six months ago I began a series of articles about designing classes and objects. In this month's Design Techniques column, I'll continue that series by looking at design principles that concern thread safety. This article tells you what thread safety is, why you need it, when you need it, and how to go about getting it.

What is thread safety?
Thread safety simply means that the fields of an object or class always maintain a valid state, as observed by other objects and classes, even when used concurrently by multiple threads.

One of the first guidelines I proposed in this column (see "Designing object initialization") is that you should design classes such that objects maintain a valid state, from the beginning of their lifetimes to the end. If you follow this advice and create objects whose instance variables all are private and whose methods only make proper state transitions on those instance variables, you're in good shape in a single-threaded environment. But you may get into trouble when more threads come along.

Multiple threads can spell trouble for your object because often, while a method is in the process of executing, the state of your object can be temporarily invalid. When just one thread is invoking the object's methods, only one method at a time will ever be executing, and each method will be allowed to finish before another method is invoked. Thus, in a single-threaded environment, each method will be given a chance to make sure that any temporarily invalid state is changed into a valid state before the method returns.

Once you introduce multiple threads, however, the JVM may interrupt the thread executing one method while the object's instance variables are still in a temporarily invalid state. The JVM could then give a different thread a chance to execute, and that thread could call a method on the same object. All your hard work to make your instance variables private and your methods perform only valid state transformations will not be enough to prevent this second thread from observing the object in an invalid state.

Such an object would not be thread-safe, because in a multithreaded environment, the object could become corrupted or be observed to have an invalid state. A thread-safe object is one that always maintains a valid state, as observed by other classes and objects, even in a multithreaded environment.

Why worry about thread safety?
There are two big reasons you need to think about thread safety when you design classes and objects in Java:

  1. Support for multiple threads is built into the Java language and API
  2. All threads inside a Java virtual machine (JVM) share the same heap and method area

Because multithreading is built into Java, it is possible that any class you design eventually may be used concurrently by multiple threads. You needn't (and shouldn't) make every class you design thread-safe, because thread safety doesn't come for free. But you should at least think about thread safety every time you design a Java class. You'll find a discussion of the costs of thread safety and guidelines concerning when to make classes thread-safe later in this article.

Given the architecture of the JVM, you need only be concerned with instance and class variables when you worry about thread safety. Because all threads share the same heap, and the heap is where all instance variables are stored, multiple threads can attempt to use the same object's instance variables concurrently. Likewise, because all threads share the same method area, and the method area is where all class variables are stored, multiple threads can attempt to use the same class variables concurrently. When you do choose to make a class thread-safe, your goal is to guarantee the integrity -- in a multithreaded environment -- of instance and class variables declared in that class.

You needn't worry about multithreaded access to local variables, method parameters, and return values, because these variables reside on the Java stack. In the JVM, each thread is awarded its own Java stack. No thread can see or use any local variables, return values, or parameters belonging to another thread.

Given the structure of the JVM, local variables, method parameters, and return values are inherently "thread-safe." But instance variables and class variables will only be thread-safe if you design your class appropriately.

RGBColor #1: Ready for a single thread
As an example of a class that is not thread-safe, consider the RGBColor class, shown below. Instances of this class represent a color stored in three private instance variables: r, g, and b. Given the class shown below, an RGBColor object would begin its life in a valid state and would experience only valid-state transitions, from the beginning of its life to the end -- but only in a single-threaded environment.

// In file threads/ex1/RGBColor.java
// Instances of this class are NOT 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);

        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];
        retVal[0] = r;
        retVal[1] = g;
        retVal[2] = b;

        return retVal;
    }

    public 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();
        }
    }
}

Because the three instance variables, ints r, g, and b, are private, the only way other classes and objects can access or influence the values of these variables is via RGBColor's constructor and methods. The design of the constructor and methods guarantees that:

  1. RGBColor's constructor will always give the variables proper initial values
  2. Methods setColor() and invert() will always perform valid state transformations on these variables
  3. Method getColor() will always return a valid view of these variables

Note that if bad data is passed to the constructor or the setColor() method, they will complete abruptly with an IllegalArgumentException. The checkRGBVals() method, which throws this exception, in effect defines what it means for an RGBColor object to be valid: the values of all three variables, r, g, and b, must be between 0 and 255, inclusive. In addition, in order to be valid, the color represented by these variables must be the most recent color either passed to the constructor or setColor() method, or produced by the invert() method.

If, in a single-threaded environment, you invoke setColor() and pass in blue, the RGBColor object will be blue when setColor() returns. If you then invoke getColor() on the same object, you'll get blue. In a single-threaded society, instances of this RGBColor class are well-behaved.

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.

For some reason, your browser won't let you see this way cool Java applet.

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.

Read/write conflicts
Another kind of misbehavior that may be exhibited in a multithreaded environment by instances of this RGBColor class is read/write conflicts. This kind of conflict arises when an object's state is read and used while in a temporarily invalid state due to the unfinished work of another thread.

For example, note that during the blue thread's execution of the setColor() method above, the object at one point finds itself in the temporarily invalid state of black. Here, black is a temporarily invalid state because:

  1. It is temporary: Eventually, the blue thread intends to set the color to blue.
  2. It is invalid: No one asked for a black RGBColor object. The blue thread is supposed to turn a green object into blue.

If the blue thread is preempted at the moment the object represents black by a thread that invokes getColor() on the same object, that second thread would observe the RGBColor object's value to be black.

Here's a table that shows a sequence of events that could lead to just such a read/write conflict:

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 getColor() 0 0 0  
red int[] retVal = new int[3]; 0 0 0  
red retVal[0] = 0; 0 0 0  
red retVal[1] = 0; 0 0 0  
red retVal[2] = 0; 0 0 0  
red return retVal; 0 0 0  
red red thread returns black 0 0 0  
blue later, blue thread continues 0 0 0  
blue this.b = 255 0 0 0  
blue blue thread returns 0 0 255  
none object represents blue 0 0 255  

As you can see from this table, the trouble begins when the blue thread is interrupted when it has only partially finished painting the object blue. At this point the object is in a temporarily invalid state of black, which is exactly what the red thread sees when it invokes getColor() on the object.

Three ways to make an object thread-safe
There are basically three approaches you can take to make an object such as RGBThread thread-safe:

  1. Synchronize critical sections
  2. Make it immutable
  3. Use a thread-safe wrapper

Approach 1: Synchronizing the critical sections
The most straightforward way to correct the unruly behavior exhibited by objects such as RGBColor when placed in a multithreaded context is to synchronize the object's critical sections. An object's critical sections are those methods or blocks of code within methods that must be executed by only one thread at a time. Put another way, a critical section is a method or block of code that must be executed atomically, as a single, indivisible operation. By using Java's synchronized keyword, you can guarantee that only one thread at a time will ever execute the object's critical sections.

To take this approach to making your object thread-safe, you must follow two steps: you must make all relevant fields private, and you must identify and synchronize all the critical sections.

Step 1: Make fields private
Synchronization means that only one thread at a time will be able to execute a bit of code (a critical section). So even though it's fields you want to coordinate access to among multiple threads, Java's mechanism to do so actually coordinates access to code. This means that only if you make the data private will you be able to control access to that data by controlling access to the code that manipulates the data.

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.

For some reason, your browser won't let you see this way-cool Java applet.

To step through the sequence of events that led 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 blue thread acquires lock 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 red thread blocks because object locked 0 0 0  
blue later, blue thread continues 0 0 0  
blue this.b = 255 0 0 0  
blue blue thread returns and releases lock 0 0 255  
red later, red thread acquires lock and continues 0 0 255  
red checkRGBVals(255, 0, 0); 0 0 255  
red this.r = 255; 0 0 255  
red this.g = 0; 255 0 255  
red this.b = 0; 255 0 255  
red red thread returns and releases lock 255 0 0  
none object represents red 255 0 0  

Note that this version of RGBColor still has temporarily invalid states from time to time. To be specific, at times during the sequence shown above this object's state does represent the invalid states black and magenta. The trick to synchronization is that while an object is having one of those temporarily invalid moments, no other classes or objects are allowed to use or observe the state of the object via other threads.

Approach 2: Immutable objects
An alternative way to make an object thread-safe is to make the object immutable. An immutable object is one whose state can't be changed once the object is created.

Immutable objects are, by their very nature, thread-safe simply because threads have to be able to write to an object's instance variables to experience a read/write or write/write conflict. Because no methods (only the constructor) of an immutable object actually write to the object's instance variables, the object is by definition thread-safe.

In this approach to making an object thread-safe, you don't mark critical sections as synchronized. Instead, you separate out the critical sections that read instance variables from those that write to instance variables. The critical sections that read are left as-is. The critical sections that write must be changed so that, instead of altering the current object's instance variables, they create a new object that embodies the new state and returns a reference to that object.

RGBColor # 3: Thread safety through immutability
Here's an immutable version of RGBColor:

// In file threads/ex3/RGBColor.java
// Instances of this immutable class
// are thread-safe.
public class RGBColor {

    private final int r;
    private final int g;
    private final int b;

    public RGBColor(int r, int g, int b) {

        checkRGBVals(r, g, b);

        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];
        retVal[0] = r;
        retVal[1] = g;
        retVal[2] = b;

        return retVal;
    }

    public RGBColor invert() {

        RGBColor retVal = new RGBColor(255 - r,
            255 - g, 255 - b);

        return retVal;
    }

    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();
        }
    }
}

Note that the setColor() method is simply removed, as it doesn't make sense in an immutable RGBColor object. The getColor() method, which reads the instance variables, is identical to what it has been, except now it doesn't have to be synchronized. The invert() method, which writes to the instance variables, is changed. Instead of inverting the current object's color, this new invert() creates a new RGBColor object that represents the inverse of the object upon which invert() is invoked, and returns a reference to that object.

Approach 3: Thread-safe wrappers
The third approach to making an object thread-safe is to embed that object in a thread-safe wrapper object. In this approach you leave the original class (which isn't thread-safe) unchanged and create a separate class that is thread-safe. Instances of the new class serve as thread-safe "front ends" to instances of the original class.

SafeRGBColor: A thread-safe wrapper
Here's an example of this approach applied to the very first version of RGBColor presented in this article.

// In file threads/ex1/SafeRGBColor.java
// Instances of this class are thread-safe
// wrappers of RGBColor objects, which are
// not thread-safe.
public class SafeRGBColor {

    private RGBColor color;

    public SafeRGBColor(int r, int g, int b) {

        color = new RGBColor(r, g, b);
    }

    public synchronized void setColor(int r, int g, int b) {

        color.setColor(r, g, b);
    }

    /**
    * returns color in an array of three ints: R, G, and B
    */
    public synchronized int[] getColor() {

        return color.getColor();
    }

    public synchronized void invert() {

        color.invert();
    }
}

Why not just synchronize everything?
As mentioned earlier in this article, you don't want to make every class you design thread-safe -- only classes whose instances will be used concurrently by multiple threads. The reason you don't want to make every class thread-safe is that thread safety may involve a performance penalty. For example:

  • Synchronized method invocations generally are going to be slower than non-synchronized method invocations. In Sun's current JVM, for example, synchronized method invocations are 4 to 6 times slower than non-synchronized method invocations. In the future, the speed of synchronized method invocations should improve, but they will likely never achieve parity with non-synchronized method invocations.
  • Unnecessary synchronized method invocations (and synchronized blocks) can cause unnecessary blocking and unblocking of threads, which can hurt performance.
  • Immutable objects tend to be instantiated more often, leading to greater numbers of often short-lived objects that can increase the work of the garbage collector.
  • Synchronization gives rise to the possibility of deadlock, a severe performance problem in which your program appears to hang.

None of these performance setbacks are good excuses for neglecting to make classes that need to thread-safe so, but they do constitute good reasons not to make classes thread-safe unnecessarily.

Pros and cons of the three approaches to thread safety
Synchronizing critical sections
Marking your code's critical sections as synchronized is the "normal" approach to making classes synchronized. It is also the only way to use wait() and notify() to get threads to cooperate towards achieving some common goal. So the guideline concerning Approach 1 is simply:

Unless special circumstances make it appropriate to use an immutable or wrapper object, use Approach 1 to make your class thread-safe: Make sure the appropriate instance variables are private and mark the critical sections as synchronized.

Using immutable objects
Achieving thread safety by making objects immutable (Approach 2) works well when objects are small and represent values of a simple abstract data type. The Java API includes several examples of immutable objects, including String and the primitive type wrappers such as Integer, Long, Float, Boolean, Character, and so on.

It's worth noting that instances of the AWT's Color class are immutable. Likewise, the immutable approach may make sense for this article's RGBColor class, which is similar in functionality to the AWT's Color class, because RGBColor objects are small (they contain only 3 ints) and conceptually represent values of a simple abstract data type.

Another benefit of immutable objects is that you can pass references to them to methods without worrying that the method will change the object's state. In addition, if the overhead of immutability (excessive creation of short-lived objects) may at times be too inefficient, you can also define a mutable companion class that can be used when the immutable version isn't appropriate. An example of this design approach in the Java API is the StringBuffer class, which serves as a mutable companion to the immutable String class. Note that the StringBuffer class is also thread-safe, but it uses the "normal" approach: its instance variables are private and its critical sections are synchronized.

Using wrapper objects
The wrapper object approach to thread safety (Approach 3) makes the most sense when you want to give clients a choice between a version of a class that is thread-safe and one that isn't. This approach also makes sense when you're a client of someone else's class that isn't thread-safe, but you need to use the class in a multithreaded environment. Once you define your own thread-safe wrapper for the class, you can safely use the class in a multithreaded environment by going through your wrapper.

A good example of this approach from the Java API comes from the 1.2 collections library. The 1.2 collections library defines a hierarchy that includes classes that represent many kinds of collections -- none of which are thread-safe. But class Collection includes several class methods that will enclose a regular collection object in a thread-safe wrapper, so you can safely use the object in a multithreaded context. This design gives users of the collections library a choice of using a collections object that is thread-safe and one that isn't.

Note that a common attribute of wrapper classes like those you would use to add thread safety to the enclosed object is that the wrapper accepts the same messages as the enclosed object. In other words, often a wrapper class will descend from a common superclass or superinterface with the enclosed class. (For those of you familiar with the Design Patterns book by Gamma, et. al., this is the "decorator" pattern. See Resources for more information on this book.) This decorator design approach to wrappers, which is exhibited by the thread-safe wrappers of the 1.2 collections library, allows the thread safety to be dynamically added or removed from an object.

The advantage of the approach to wrapping taken by SafeRGBColor in this article is that thread safety is guaranteed when using a SafeRGBColor object, because the enclosed RGBColor object is created by SafeRGBColor's constructor and never returned by its own methods or passed to another object's methods. The decorator design approach, because the enclosed object is instantiated by the client and passed to the constructor of the thread-safe wrapper, requires that clients create the enclosed objects themselves first. Thus, to achieve thread safety, the decorator approach requires that clients have the discipline not to use the enclosed object except through the thread-safe wrapper.

When to make classes thread-safe
When you are designing the classes that compose a Java applet or application, your thread-safety decision should be based simply on whether or not each class will be exposed to potential write/write or read/write conflicts by your programs. To know whether or not such conflicts are possible, you just have to know how your program will work.

For example, I didn't choose thread safety for any of the classes that compose the two simulation applets included above in this article, because they won't be exposed to multiple threads. Once the init() method of the applet has returned, the only thread that will be coursing through the veins of this code is the GUI event handler thread -- and there is only one GUI event handler thread. As a result, even if a user frantically clicks the Reset button as quickly as possible after the Step button, the code of my applet will handle the Step button press completely before beginning to handle the Reset button press.

By contrast, I did make thread-safe certain classes that compose the JVM Simulation applets that are delivered on the CD-ROM of my JVM book (see Resources). These applets have Run and Stop buttons as well as Step and Reset buttons. When the user clicks Run, I fire off a thread that animates the applet, making the applet run as if the user were clicking Step about twice a second. When the user clicks Stop, the event handler thread comes in to stop the animation thread but mustn't be allowed to do so before the run thread completes its current step and puts the JVM simulator into a valid state.

If, instead of creating classes for an applet or application, you are creating classes for a library, either one that will be shared in-house or will serve as a product in its own right, you have a different problem. You may not know exactly how the classes will be used. In such cases, it may be a good idea to give clients a choice via the thread-safe wrapper approach.

Conclusion
The most important point to take away from this article is that when programming in Java, you should at least think about thread safety every time you design a class.

Here's a collection of the exception guidelines put forth by this article:

  • Given that thread safety can have a performance cost, don't make every class thread-safe -- only those classes that will actually be used concurrently by multiple threads
  • Don't avoid making classes thread-safe that need to be thread-safe out of fear of a performance impact
  • When making an object thread-safe via Approach 1, synchronize only the critical sections of the class
  • Use an immutable object especially if the object is small or represents a fundamental data type
  • If you can't change a non-thread-safe class, use a wrapper object
  • If you are creating a library of classes that will be used in both thread-safe and non-thread-safe requirements, consider making wrappers an option

Next month
In next month's installment of Design Techniques, I'll continue the series of articles that focus on designing classes and objects. Next month's article, the seventh of this series, will discuss design guidelines that pertain to making an object observable.

A request for reader participation
I encourage your comments, criticisms, suggestions, flames -- all kinds of feedback -- about the material presented in this column. If you disagree with something, or have something to add, please let me know.

You can either participate in a discussion forum devoted to this material or e-mail me directly at bv@artima.com.

Resources

This article was first published under the name Design for Thread Safety in JavaWorld, a division of Web Publishing, Inc., July 1998.

Talk back!

Have an opinion? Be the first to post a comment about this article.

About the author

Bill Venners has been writing software professionally for 12 years. Based in Silicon Valley, he provides software consulting and training services under the name Artima Software Company. Over the years he has developed software for the consumer electronics, education, semiconductor, and life insurance industries. He has programmed in many languages on many platforms: assembly language on various microprocessors, C on Unix, C++ on Windows, Java on the Web. He is author of the book: Inside the Java Virtual Machine, published by McGraw-Hill.