TICS Coding Standard Viewer 
TIOBE Software Quality Framework
Print-friendly version
©TIOBE Software www.tiobe.com
 
TIOBE - Java Coding Standard
Search

Rule:  Basic11Checked automatically with code checker

Synopsis:Double checked locking is not thread safe in Java
Language:Java
Severity Level:1
Category:Basic


Description:
Partially created objects can be returned by the Double Checked Locking pattern when used in Java. An optimizing JRE may assign a reference to the baz variable before it creates the object the reference is intended to point to.
public class Foo {
  Object baz;

  Object bar() {
    if(baz == null) { //baz may be non-null yet not fully created
      synchronized(this){
        if(baz == null){
          baz = new Object();
        }
      }
    }
    return baz;
  }
}

Justification:

First of all, because the null-check is outside of the synchronized block when 2 threads are "simultaneously" doing the null-check then both will enter the if-statement. One of them will enter the synchronized block, and the other one is stopped. The first one will create a new Object and leave the synchronized block. That allows the 2nd thread to enter the synchronized block and create another Object. The 2nd thread will still create another Object because compiler generation of the instructions for writes that initialize the "baz" Object may be executed after.

One of the suggested fixes is to declare the baz object as volatile:

   public class Foo { 
     volatile Object baz; 

     Object bar() { 
         if(baz == null) { //baz may be non-null yet not fully created 
           synchronized(this) { 
                if(baz == null){
                   baz = new Object(); 
                } 
             } 
         } 
         return baz; 
     } 
 } 

However, even if JVM prevents writes to volatile variables to be reordered and ensures that they are flushed to main memory immediately, it still permits reordering of reads and writes instructions for volatile variable with respect to reads and writes for nonvolatile variables. Which means, considering two threads A and B, unless all fields of "baz" type class are volatile as well, thread B can still perceive the constructor's effect as happening after "baz" object is set to reference by the thread A.

For more details see http://www.javaworld.com/javaworld/jw-02-2001/jw-0209-double.html.