Newsletter sign-up
View all newsletters

Enterprise Java Newsletter
Stay up to date on the latest tutorials and Java community news posted on JavaWorld

Sponsored Links

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

Programming Java threads in the real world, Part 7

Singletons, critical sections, and reader/writer locks

  • Print
  • Feedback
This month I'm going to tie up a few synchronization-related loose ends left over from my previous Java Toolbox installments in this series. I'll start out looking at singletons, or one-of-a-kind objects. These are surprisingly difficult to implement efficiently in a multithreaded environment, but are essential in most programs. (java.awt.Toolkit is an example of a singleton.) Along the way, I'll also look at critical sections, or blocks of code -- as compared to objects -- that can be locked.

I'll finish up with a completely unrelated topic: reader/writer locks, which give you efficient, thread-safe access to read/write resources such as data structures and files. Reader/writer locks are simple enough to implement that I didn't want to devote an entire column to them, but they're essential in any multithreaded program that performs I/O operations, so I wanted to include them in the present series of articles. Reader/writer locks combined with the various semaphores and locks I've presented in previous installments of this series comprise a reasonably complete toolkit for solving thread-related synchronization problems.

Critical sections, singletons, and the Class object

So far in this series I've been concentrating on the monitor -- a means of locking an entire object while a body of code is being executed. The other essential sort of lock you should be aware of is the critical section. Critical sections are essential in implementing one-time initialization code when that code can be accessed from multiple threads.

A critical section is a chunk of code that can be executed by only one thread at a time. Compare this notion with a normal synchronized code block -- a monitor -- which is basically an exclusion semaphore that guards an entire object. Several threads can simultaneously execute a synchronized method, but only if the objects that are receiving the associated messages are different. In a critical section, the code itself is locked, not the object. Only one thread can be in the critical section at a time, even if the receiving objects are different. The mutex that guards a monitor is an object-level mutex; the mutex that guards a critical section is effectively a class-level mutex. Think of it this way: the code is defined in the class, not the object, so when you're locking the code itself, you're locking the entire class of objects. (By the way, I've seen authors get this wrong in print when they call a block of code inside a nonstatic method a "critical section." A block of code in a nonstatic method is part of the object's monitor; it is not a critical section.)

Static members
In Java, the notion of a critical section is closely tied to that of a static member, so let's start there. Java, like all OO languages, supports two categories of fields and methods:

Class variables: variables that control the state of all objects within a class.
Instance variables: variables that control the state of a single object within a class.


A class variable is implemented in Java by placing a static keyword before its definition.

  • Print
  • Feedback

Resources
  • Bill Venners discussed static members, though without much coverage of the implementation issues, in his Design Techniques column, "Design with static members" http://www.javaworld.com/javaworld/jw-03-1999/jw-03-techniques.html
  • The Singleton pattern is presented in the "Gang of Four" (or GoF) bookErich Gamma, Richard Helm, Ralph Johnson, and John Vlissides's Design Patterns Elements of Reusable Object-Oriented Software (Reading, MAAddison Wesley, 1995). This book is essential reading for any OO designer.
  • John Vlissides's Pattern HatchingDesign Patterns Applied (Reading, MAAddison Wesley, 1998) also has a lot to say about singletons in Chapter 2 and the first section of Chapter 3.
  • The double-checked locking strategy for singleton creation is described in "Double-Checked Locking" by Douglas C. Schmidt and Tim Harrison, Pattern Languages of Program Design 3 (Reading, MAAddison Wesley, 1998, pp. 363-375).
  • Reader/writer locks are described in Doug Lea's Concurrent Programming in Java (Reading, MAAddison Wesley, 1997, pp. 300-303). My implementation is based on Lea's.
  • Reader/writer locks are also described in Scott Oaks and Henry Wong's Java Threads (Sebastopol, CAO'Reilly, 1997, pp. 180-187).