JD.SYNC.DCL

JD.SYNC.DCL occurs when double-checked locking is found (as in first the example below).

Vulnerability and risk

Double-checked locking is widely cited and used as an efficient method for implementing lazy initialization in a multithreaded environment. Unfortunately, it will not work reliably in a platform independent way when implemented in J2SE 1.4 (and earlier versions). Although the double-checked locking idiom cannot be used for references to objects, it can work for 32-bit primitive values (e.g., int's or float's). Note, that it does not work for long's or double's, since unsynchronized reads/writes of 64-bit primitives are not guaranteed to be atomic.

The double-checked locking pattern will not work when under certain circumstances the code, generated by compiler, will contain assignment of an incompletely initialized object to a field before statements, that finalize the object initialization. Thus other threads will see a non-null reference to an object with default field values. Even if the compiler does not reorder those statements, on a multiprocessor system the processor or the memory system may reorder those statements, as perceived by a thread running on another processor.

Mitigation and prevention

As of J2SE 5.0, this problem has been fixed. The 'volatile' keyword now ensures that multiple threads handle the singleton instance correctly. If the singleton that is created is static, the solution will be to define the singleton as a static field in a separate class. The semantics of Java guarantee that the field will not be initialized until the field is referenced, and that any thread which accesses the field will see all of the writes resulting from initializing that field. Otherwise, one can use synchronization without a double check, but should keep in mind that synchronizing a method may decrease performance significantly (see second example below). For more information see the Wikipedia article: Double-checked locking.

Example 1

Copy
      class MyClass {
         MyClass son;
         void doubleCheckedLocking() {
             if (son==null) {
                 synchronized (this) {
                     if (son==null) {
                         son = new MyClass();
                     }
                 }
             }
         }
     }

JD.SYNC.DCL is reported for line 14: Double-checked locking for 'son' -- idiom that does not achieve its goal.

Example 2

Copy
     class MyClass {
         private MyClass son = null;
         public synchronized void doubleCheckedLocking() {
             if (son == null)
                 son = new MyClass();
         }
     }

Method is synchronized, no need for double checks.