Double-checked locking: Clever, but broken

Do you know what synchronized really means?

Page 2 of 2

One special case of lazy initialization that does work as expected without synchronization is the static singleton. When the initialized object is a static field of a class with no other methods or fields, the JVM effectively performs lazy initialization automatically. In the following example, the Resource will not be constructed until the field resource is first referenced by another class, and any memory writes that result from resource's initialization are automatically visible to all threads:

class MySingleton {
  public static Resource resource = new Resource();
}

The initialization will be performed when the JVM initializes the class. Since MySingleton has no other fields or methods, class initialization occurs when the resource field is first referenced.

DCL also works with 32-bit primitive values. If the resource field in SomeClass were an integer (but not a long or a double), then SomeClass would behave as expected. However, you cannot use this behavior to fix the problems with DCL when you want to lazily initialize an object reference or more than one primitive value.

Will the JMM be fixed?

Bill Pugh of the University of Maryland is preparing a Java Specification Request (JSR) to fix some of the problems with the current JMM. These improvements include:

  • Clarification of the JMM
  • Relaxation of some requirements to allow for common compiler optimizations
  • Reduction of synchronization's performance impact in the absence of real contention
  • Modifications to volatile's semantics in order to prevent reordering of writes to volatile variables with writes to other variables

At the time of this writing, this JSR has not yet entered the Java Community Process.

Conclusion

The JMM was the first attempt to define shared memory semantics in the context of the language specification for a general-purpose programming language. Unfortunately, it is quite complicated, poorly understood, and not consistently implemented across JVMs. Not surprisingly, the JMM's complexity resulted in JVM implementation errors and widespread misunderstandings among users -- such as the misperception of how synchronized works, which leads to unsafe idioms like DCL. While there are proposals on the table for a simpler memory model, it will be quite a while before we see such fundamental changes to the Java specification, if ever.

In the meantime, carefully examine your multithreaded programs to ensure that any reference to a variable written by another thread is properly synchronized.

Brian Goetz is a professional software developer with over 15 years of experience. He is a principal consultant at Quiotix, a software development and consulting firm located in Los Altos, Calif.

Learn more about this topic

  • Double-checked locking idiom:
  • The Java Memory Model and multithreaded programming

Related:
| 1 2 Page 2