Lazy initialization

Lazy initialization holder class idiom for static fields
Utilize JVM’s lazy class loading to create a lazy initialization technique that doesn’t require synchronization on the common code path.

public class ResourceFactory {
 private static class ResourceHolder {
  public static Resource resource=new Resource();
}
public static Resource getResource(){
 return ResourceHolder.resource;
}
}

JVM defers initializing the ResourceHolder class until it is actually used [1] and because Resource is initialized with a static initializer, no additional synchronization is required. The first call to getResource by any thread causes ResourceHolder to be loaded and initialized, at which time the initialization of the Resource happens through static initializer. A modern VM will synchronize field access only to initialize the class. Once the class is initialized, the VM will patch the code so that subsequent access to the field does not involve any testing or synchronization.

Double-checked locking idiom for lazy initialization of instance fields
Double-checked locking (DCL) purported to offer best of the both worlds– lazy initialization without paying the synchronization penalty on the common code path. The way it worked was first to check whether initialization was needed without synchronizing, and if resource reference was not null, use it. Otherwise, synchronize and check again if the Resource initialized, ensuring that only one thread actually initialize the shared Resource. the common path–fetching a reference to an already constructed Resource–doesn’t use synchronization. And that’s where the problem is, it is possible for a thread to see a partially constructed Resource.

The real problem with DCL is the assumption that the worst thing that can happen when reading a shared object reference without synchronization is to erroneously see a stale value (in this case, null) ; in that case the DCL idiom compensates for the risk by trying again with the lock held. But the worst case is actually considerably worse– it is possible to see a current value of the reference but stale value of object’s state, meaning that the object could been to be in an invalid or incorrect state.

Subsequent changes to Java 5.0 and later have enabled DCL to work if resource is made volatile, and the performance impact of this small since volatile reads are usually only slightly more expensive than nonvolatile reads.

public class DoubleCheckedLocking {
  private volatile Resource resource;

  public Resource getResource () {
    Resource result=this.resource;
    if(result == null) { // first check without locking
       synchronized(this) {
       result=this.resource;
       if(result == null) { // second check with locking
             this.resource=result=computeResourceValue();
       }
     }
    }
    return result;
  }
}

What is the need to local field result?
Ensure that this.resource is read only once in the common case where it’s already initialized. While not strictly necessary, this may improve performance.

Single-checked no-locking idiom can cause repeated initialization
If you need lazily initialized instance field that can tolerate repeated intialization, you can use single-checked idiom.

public class SingleCheckedNoLocking {
  private volatile Resource resource;
  public Resource getResource () {
    Resource result=this.resource;
    if(result == null) { // first check without locking
      this.resource=result=computeResourceValue();
    }
    return result;
  }
}

All of the initialization techniques discussed here apply to primitive fields as well as object reference fields.

Racy Single-checked idiom
If you don’t care whether every thread recalculates the value of a field, and the type of the field is a primitive (other than long and double [2]), then you may choose to remove the volatile modifier from the field declaration in the single-check idiom. It is called racy single-checked idiom because it relies on data-race to publish field value. It spees up the field acess on some architectures, at the expense of additional initializations (up to one per thread that access the field). This is not for every day use and should be used with great caution because it is “racy”. It used by string instances to cache their hash codes.

public class SinlgeCheckedRacy {
  private Resource resource; // removing volatile, 
  // relying on data-race for publication

  public Resource getResource () {
    Resource result=this.resource;
    if(result == null) { // first check without locking
      this.resource=result=computeResourceValue();
    }
    return result;
  }
}

P.S.: The force that motivated these idioms (slow uncontented synchronization, slow JVM startup) are no longer in play, making it less effective as an optimization.

1. 12.4.1 When Initialization Occurs, The Java Language Specification, 3rd Ed
2. 17.7 Non-atomic Treatment of double and long, Java Language Specification, 3rd Ed

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s