Threading : Lazy Initialization vs Static Lazy Initialization Threading : Lazy Initialization vs Static Lazy Initialization multithreading multithreading

Threading : Lazy Initialization vs Static Lazy Initialization


Well both implementations can be static so that is the first misunderstanding. The presenter in this video is explaining how you can exploit the thread-safety of class initialization.

Class initialization is inherently thread-safe and if you can have an object initialized on class initialization the object creation too are thread-safe.

Here is an example of a thread-safe statically initialized object

public class MySingletonClass{   private MySingletonClass(){   }   public static MySingletonClass getInstance(){         return IntiailizationOnDemandClassholder.instance;   }   private static class IntiailizationOnDemandClassHolder{         private static final MySingletonClass instance = new MySingletonClass();   }}

What is important to know here, MySingletonClass instance variable will never be created and or initialized until getInstance() is invoked. And again since class initialization is thread-safe the instance variable of IntiailizationOnDemandClassholder will be loaded safely, once and is visible to all threads.

To answer your edit depends on your other type of implementation. If you want to do double-checked-locking your instance variable would need to be volatile. If you do not want DCL then you will need to synchronize access each time to your variable. Here are the two examples:

public class DCLLazySingleton{  private static volatile DCLLazySingleton instance;  public static DCLLazySingleton getInstace(){     if(instance == null){        synchronized(DCLLazySingleton.class){            if(instance == null)                instance=new DCLLazySingleton();        }     }      return instance;}

and

public class ThreadSafeLazySingleton{   private static ThreadSafeLazySingleton instance;  public static ThreadSafeLazySingleton getInstance(){     synchronized(ThreadSafeLazySingleton.class){        if(instance == null){            instance = new ThreadSafeLazySingleton();        }        return instance;     } }

The last example requires a lock acquisition on every request of the instance. The second example requires a volatile-read on each access (may be cheap or not, depends on the CPU).

The first example will always lock once regardless of the CPU. Not only that but each read will be a normal without any need to worry about thread-safety. I personally like the first example I have listed.


It is worth noting that the simplest thread safe static lazy initialisation is to use an enum This works because initialisation of static fields is thread safe and classes are lazily loaded anyway.

enum ThreadSafeLazyLoadedSingleton {    INSTANCE;}

A class which uses a lazy loaded value is String. The hashCode is only computed the first time it is used. After that the cached hashCode is used.

I don't think you can say that one is better than the other because they are not really interchangeable.


I think the author in the presentation refers to the fact that a static field would be initialized only once in a thread-safe way at the first use of the class which contains that field (this is guaranteed by JMM):

class StaticLazyExample1 {   static Helper helper = new Helper();   static Helper getHelper() {      return helper;   }}

Here helper field would be initialized upon first usage of StaticLazyExample1 class (i.e. upon constructor or static method call)

There is also Initialization On Demand Holder idiom, which is based on static lazy initialization:

class StaticLazyExample2 {  private static class LazyHolder {    public static Helper instance = new Helper();  }  public static Helper getHelper() {    return LazyHolder.instance;  }}

Here a Helper instance would be created only upon first call to StaticLazyExample2.getHelper() static method. This code is guaranteed to be thread-safe and correct because of the initialization guarantees for static fields; if a field is set in a static initializer, it is guaranteed to be made visible, correctly, to any thread that accesses that class.

UPDATE

What is the difference between both types of initialization?

The static lazy initialization provides efficient thread safe lazy initialization of the static fields and has zero synchronization overhead.On the other hand if you would like to lazily initialize a non-static field, you should write something like this:

class LazyInitExample1 {  private Helper instance;  public synchronized Helper getHelper() {    if (instance == null) instance == new Helper();    return instance;  }}

Or use Double-Cheked Locking idiom:

class LazyInitExample2 {    private volatile Helper helper;    public Helper getHelper() {      if (helper == null) {          synchronized (this) {              if (helper == null) helper = new Helper();          }      }      return helper;    }}

Should I mention they both require explicit synchronization and carry additional timing overhead comparing to static lazy initialization?