Double checking in Java (Double Check)

  • 2020-05-05 11:17:01
  • OfStack

The double-check pattern is mentioned in article 48 of Effecitve Java, and it is pointed out that this pattern is generally not applicable in Java. The structure of the pattern is as follows:


public Resource getResource() { 
 if (resource == null) {  
  synchronized(this){  
   if (resource==null) { 
    resource = new Resource();  
   }   
  }  
 } 
 return resource; 
}

  this pattern is an improvement on the following code:


public synchronized Resource getResource(){ 
 if (resource == null){  
    resource = new Resource();  
 } 
 return resource; 
} 

The purpose of this code is to lazily initialize resource. But you need to synchronize each access. To reduce the overhead of synchronization, a double-checked pattern is introduced.

The reason the double-checked pattern is invalid in Java is that the reference type is not thread-safe when out of sync. For basic types other than long and double, the double-check pattern is applicable. For example, the following code is correct:


private int count; 
public int getCount(){ 
 if (count == 0){  
  synchronized(this){  
   if (count == 0){ 
    count = computeCount(); // A time-consuming calculation  
   }   
  }  
 } 
 return count; 
} 

The above is the general conclusion about the double-checked mode in java (double-check idiom). But that's not the end of the story, as the java memory model is also being improved. "According to the latest Java memory model of JSR133, the double-checked pattern works if the reference type is declared as volatile," Doug Lea writes in his article. So to use the double-checked mode in Java in the future, you can use the following code:


private volatile Resource resource; 
public Resource getResource(){ 
 if (resource == null){  
  synchronized(this){  
   if (resource==null){ 
    resource = new Resource();  
   }   
  }  
 } 
 return resource; 
} 

 , of course, has to be in Java following the JSR133 specification.

Therefore, double-check is not available in J2SE 1.4 or earlier versions due to out-of-order writes for multi-threading or JVM tuning. This issue has been fixed in J2SE 5.0, and the volatile keyword can be used to guarantee singletons in multiple threads.


public class Singleton { 
  private volatile Singleton instance = null; 
  public Singleton getInstance() { 
    if (instance == null) { 
      synchronized(this) { 
        if (instance == null) { 
          instance = new Singleton(); 
        } 
      } 
    } 
    return instance; 
  } 
} 

The recommended methods are Initialization on Demand Holder (IODH),


public class Singleton { 
  static class SingletonHolder { 
    static Singleton instance = new Singleton(); 
  } 
   
  public static Singleton getInstance(){ 
    return SingletonHolder.instance; 
  } 
} 

The above is the entire content of this article, I hope to help you learn java programming.


Related articles: