Design for thread safety

Design tips on when and how to use synchronization, immutable objects, and thread-safe wrappers

1 2 3 Page 3
Page 3 of 3

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 even 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, enter a comment via the form at the bottom of the article, or e-mail me directly using the link provided in my bio below.

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.

Learn more about this topic

  • The discussion forum devoted to the material presented in this article. http://www.artima.com/flexiblejava/fjf/threadsafety/index.html
  • Recommended books on Java design http://www.artima.com/designtechniques/booklist.html
  • Source packet that contains the example code used in this article http://www.artima.com/flexiblejava/code.html
  • Source code for the JVM Simulator applets, which, as mentioned in the article, include some thread-safe classes. Look at JVMSimulator and Method.java and search for sychronized. http://www.artima.com/insidejvm/applets/sourcecode.html
  • Object orientation FAQ http://www.cyberdyne-object-sys.com/oofaq/
  • 7237 Links on Object Orientation http://www.rhein-neckar.de/~cetus/software.html
  • The Object-Oriented Page http://www.well.com/user/ritchie/oo.html
  • Collection of information on OO approach http://arkhp1.kek.jp:80/managers/computing/activities/OO_CollectInfor/OO_CollectInfo.html
  • Design Patterns Home Page http://hillside.net/patterns/patterns.html
  • A Comparison of OOA and OOD Methods http://www.iconcomp.com/papers/comp/comp_1.html
  • Object-Oriented Analysis and Design MethodsA Comparative Review http://wwwis.cs.utwente.nl:8080/dmrg/OODOC/oodoc/oo.html
  • Patterns discussion FAQ http://gee.cs.oswego.edu/dl/pd-FAQ/pd-FAQ.html
  • Implementing Basic Design Patterns in Java (Doug Lea) http://www.oswego.edu/dl/pats/ifc.html
  • Patterns in Java AWT http://mordor.cs.hut.fi/tik-76.278/group6/awtpat.html
  • Software Technology's Design Patterns Page http://www.sw-technologies.com/dpattern/
  • Previous Design Techniques articles http://www.javaworld.com/topicalindex/jw-ti-techniques.html
1 2 3 Page 3
Page 3 of 3