Threading : Lazy Initialization vs Static Lazy Initialization
Asked Answered
H

6

13

I am going through Java Memory Model video presentation and author is saying it is better to use Static Lazy Initialization compared to Lazy Initialization and I do not clear understand what he wants to say.

I wanted to reach to community and would appreciate if someone can explain difference between Static Lazy Initialization and Lazy Initialization with simple java code example.

Reference: Advanced Programming Topics - Java Memory Model

Hexameter answered 14/9, 2011 at 17:33 Comment(2)
Err, the video is 57 minutes long. It's certainly interesting, but you could perhaps tell us where in the video this particular topic is discussed.Finable
Look from 43rd min to 48th min, this 5 mins discusses about Static Lazy Initialization.Hexameter
S
22

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.

Saad answered 14/9, 2011 at 17:49 Comment(9)
What is the difference between both type of initialization?Hexameter
I am going through your edits, what is exactly double checked locking?Hexameter
@Hexameter Double checked locking will first check to see if the object is initialized, if it isnt initialized then it will lock the class instance for creation. It will then check again if the object is created, if not it will create it. Since it is holding the lock it will ensure only one instance created. The issue with DLC is that it doesn't promise safe object initialization if the field isn't volatile. You can read more on that here if you like cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.htmlSaad
@JohnVint please note that your DCL version is broken. See this: ibm.com/developerworks/library/j-dcl/index.htmlCabdriver
@Cabdriver Can you explain in more detail why it's broken relative to the link?Saad
@JohnVint In the first example, where is implied that locking will be performed once. It is possible that the second thread, when checks for null, sees an initialized object, but actually the constructor called from first thread isn't completed. This implies that first thread hasn't finished the synchronized block, and so, changes are not necessarily flushed to heap memory.Cabdriver
@JohnVint N.B. new operation isn't atomic.Cabdriver
The IntiailizationOnDemandClassHolder example is thread safe. Though you are right, new isn't necessarily thread-safe, classloading is. The new assignment happens-before the releasing of the class loader lock. The second example, new is atomic due to the fact the field is volatile. Lastly, the third example is thread-safe as the new assignment happens before the releasing of the class lock and any subsequent acquisition of said lock.Saad
I did make one update to make more clear my last example is happening under the class lock.Saad
S
3

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?

Standish answered 14/9, 2011 at 17:48 Comment(6)
What is the difference between both types of initialization?Hexameter
What is Static Lazy Initialization? I am not able to understand the concept.Hexameter
Static Lazy Initialization is the lazy initialization of the static field. As presentation says: If you need to initialize a singleton value, something that will only be initialized once, lazily, per JVM - initialize it in the declaration of a static variable. Java spec guarantees it will be initialized in a thread safe way at the first use of the class, but not before. See my first two examples (StaticLazyExample classes) for the examples of Static Lazy Initialization of the static fields.Standish
And it worth to mention that you can't use Static Lazy Initialization for the lazy initialization of the non-static fields, only for static ones.Standish
Ok, so in your above two examples, first example will not be thread safe right?Hexameter
If you are talking about first of LazyInitExample it will be thread safe because instance field is written and read in the synchronized block. Perhaps I'd better remove static modifier from its getInstance method to not confuse you.Standish
F
2

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.

Fredericton answered 14/9, 2011 at 22:3 Comment(2)
I am trying to understand your answer, can you elaborate more on the difference between the two approaches, I am specifically trying to understand what is the actual difference between Lazy Initialization and Static Lazy Initialization also am not sure what presenter meant to say when he explained Static Lazy Initialization?Hexameter
AFAIK, Static Lazy Initialisation is lazy initialisation of a static field. The broader term Lazy Initialization is any lazy initialisation. (Which could include static ones) I would be tempted to use the term Non-Static Lazy Initialisation for non static fields. The reason you might distinguish these, is they have different uses. e.g. Singletons are always static.Fredericton
S
1

A reference would be good here, for sure. They both have the same basic idea: Why allocate resources (memory, cpu) if you don't have to? Instead, defer allocation of those resources until they're actually needed. This can be good in intensive environments to avoid waste, but can be very bad if you need the results right now and cannot wait. Adding a "lazy but prudent" system is very difficult (one that detects downtime and runs these lazy calculations when it gets free time.)

Here's an example of lazy initialization.

class Lazy {

    String value;
    int computed;

    Lazy(String s) { this.value = s; }

    int compute() {
        if(computed == 0) computed = value.length();
        return computed;
    }

}

Here's static lazy initializtion

class StaticLazy {

    private StaticLazy staticLazy;
    static StaticLazy getInstance() {
        if(staticLazy == null) staticLazy = new StaticLazy();
        return staticLazy;
    }
}
Songstress answered 14/9, 2011 at 17:38 Comment(4)
Can you also explain the difference too.Hexameter
if i understand your comments properly then why should one go for static lazy initialization, it seems like one should always opt for lazy initialization.Hexameter
Youtube is blocked here at work, so unfortunately I can't watch your video to see what reasons the instructor has. Personally, I don't see any difference between them. It is possible the instructor in the video and I have a difference of opinion or more likely a difference of definition. I'll try to see if I remember to watch these later and perhaps I can get back to you.Songstress
Sure, its from 43rd min to 48th min, this 5 min tries to explain static lazy initialization, also am not able to understand difference between both types of lazy initialization, may you can explain the difference more aptly?Hexameter
B
0

The distinction is the mechanism you implement the lazy initialization. By Static Lazy Initialization I assume the presenter means this solution which relies on the JVM being compliant with any version of Java (see 12.4 Initialization of Classes and Interfaces, of the Java Language Specification).

Lazy Initialization probably means lazy initialization described in many other answers to this question. Such initialization mechanisms make assumptions about the JVM that are not thread-safe until Java 5 (as Java 5 has a real memory model specification).

Berlioz answered 14/9, 2011 at 22:22 Comment(0)
P
0
  1. Lazy loading is just a fancy name given to the process of initializing a class when it’s actually needed.

  2. In simple words, Lazy loading is a software design pattern where the initialization of an object occurs only when it is actually needed and not before to preserve simplicity of usage and improve performance.

  3. Lazy loading is essential when the cost of object creation is very high and the use of the object is very rare. So this is the scenario where it’s worth implementing lazy loading.The fundamental idea of lazy loading is to load object/data when needed.

Source: https://www.geeksforgeeks.org/lazy-loading-design-pattern/

President answered 3/11, 2022 at 10:32 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.