Lazy Loading vs Eager loading in Singleton Design Pattern

Lazy Loading vs Eager Loading in Singleton Design Pattern using C#

In this article, I am going to discuss Lazy Loading vs Eager Loading in Singleton Design Patterns in C# to Achieve Thread Safety with Examples. Please read our previous article where we discussed How to Implement Thread-Safe Singleton Design Pattern in C# using Lock and Double-Check Locking mechanism with Examples. As part of this article, we are going to discuss the following pointers.

  1. What is Non-Lazy or Eager Loading?
  2. What is Lazy or Deferred Loading?
  3. Understanding The Lazy<T> Generic Class in C#.
  4. How to make the Singleton Design Pattern Thread-Safe using both Eager Loading and Lazy Loading in C#?
What is Non-Lazy or Eager Loading in C#?

The Eager Loading or Non-Lazy Loading in C# is nothing but a process in which we need to initialize the Singleton Object at the time of application start-up rather than on-demand and keep it ready in memory to be used in the future. The advantage of using Eager Loading in the Singleton Design Pattern is that the CLR (Common Language Runtime) will take care of Object Initialization and Thread Safety in Multithread Environment. That means we will not require to write any code explicitly for handling the thread safety for a multithreaded environment.

Example to Understand Non-Lazy or Eager Loading in Singleton Design Pattern:

Let’s understand How to Implement Singleton Design Pattern using Eager Loading in C# with one Example. So, create a class with the name Singleton.cs and then copy and paste the following code into it. In the below example, while creating the singleInstance variable, we are also initializing that variable and making it ready to be used in the future. This is nothing but Eager Loading of Singleton Instance. Now, the CLR will take care of object initialization as well as Thread-Safety in a Multithreaded Environment. Now, within the GetInstance() method, we need don’t need to write the object initialization, null checking, and thread-safety code as all these things are going to be handled by the CLR. As part of the GetInstance() method, we just need to return the Singleton Instance. The following example code is self-explained, so please go through the comment lines for a better understanding.

using System;
namespace SingletonDemo
{
    public sealed class Singleton
    {
        //This variable value will be increment by 1 each time the object of the class is created
        private static int Counter = 0;

        //This variable is going to store the Singleton Instance
        //Initiazling the Variable at the time of class start-up and make it ready to be used in Future
        private static readonly Singleton singleInstance = new Singleton();
        
        //The following Static Method is going to return the Singleton Instance
        //This is Thread-Safe as it use Eager Loading
        public static Singleton GetInstance()
        {
            //Now we don't need to use any NULL Checking code
            //We don't need to write Explicit code for thread-safety
            //Object initialization and Thread-Safety will be taken care by CLR as we are using Eager Loading
            //Return the Singleton Instance
            return singleInstance;
        }

        private Singleton()
        {
            //Each Time the Constructor is called, increment the Counter value by 1
            Counter++;
            Console.WriteLine("Counter Value " + Counter.ToString());
        }

        //The following method can be accessed from outside of the class by using the Singleton Instance
        public void PrintDetails(string message)
        {
            Console.WriteLine(message);
        }
    }
}

Next, modify the Main method of the Program Class as shown below. Here, you can see that using Parallel Programming, we are accessing the GetInstance() method of the Singleton class using two different threads i.e. we are accessing the Singleton Instance in a multithread environment. The following example code is self-explained, so please go through the comment lines for a better understanding.

using System;
using System.Threading.Tasks;
namespace SingletonDemo
{
    class Program
    {
        //Example to Understand Thraed-Safe Singleton Design Pattern using Eager Loading
        //When use in a Multithreaded Environment
        static void Main(string[] args)
        {
            //The following Code will Invoke both methods Parallely using two different Threads
            Parallel.Invoke(
                //Let us Assume PrintTeacherDetails method is Invoked by Thread-1
                () => PrintTeacherDetails(),
                //Let us Assume PrintStudentdetails method is Invoked by Thread-2
                () => PrintStudentdetails()
                );
            Console.ReadLine();
        }

        private static void PrintTeacherDetails()
        {
            //Thread-1 Calling the GetInstance() Method of the Singleton class
            Singleton fromTeacher = Singleton.GetInstance();
            fromTeacher.PrintDetails("From Teacher");
        }

        private static void PrintStudentdetails()
        {
            //At the same time, Thread-2 also Calling the GetInstance() Method of the Singleton Class
            Singleton fromStudent = Singleton.GetInstance();
            fromStudent.PrintDetails("From Student");
        }
    }
}

Now run the application and you will see the following output.

Example to Understand Non-Lazy or Eager Loading in Singleton Design Pattern

 

 

You can see that only one instance got created as the Counter value is 1. The above Singleton Class is thread-safe after removing the lock variables and null checking. This is because now the CLR (Common Language Runtime) will internally take care of the variable initialization as well as thread safety in the multithreaded environment as we are using Eager Loading.

What is Lazy Loading or Deferred Loading in C#?

Lazy Loading or Deferred Loading in C# is nothing but a concept that is commonly used to delay the initialization of an object until the point at which it is needed. So the main objective of Lazy Loading or Deferred Loading is to load the object on-demand or you can say object when needed. The most important point that you need to keep in mind is that you need to use Lazy loading when the cost of the object creation is very high as well as the use of that object is very rare. Lazy loading improves the performance of an application if it is used properly. 

Example to Understand Lazy or Deferred Loading in Singleton Design Pattern:

We have already discussed Lazy Loading or Deferred Loading in Singleton Design Patterns. If you remember, in our previous article we discussed How to Implement Thread-Safe Singleton Design Pattern using Lock and Double Check Locking Mechanism. These two use the Lazy Loading Mechanism i.e. the Singleton Instance is created when we access the object for the first time. The second time onwards, it uses the already created instance. In this case, as a developer, we need to write the code to make the Singleton Instance thread-safe.

With C# 4.0 onwards, we can use the Lazy<T> Generic class to make the Singleton Instance Lazy Loading. Let us proceed and see how we can implement Lazy Loading in Singleton Design Pattern using the Lazy<T> Generic Class in C#.

Example to Understand Lazy Loading of Singleton Instance using Lazy<T> Generic Class.

The Lazy<T> Generic Class which was introduced as part of .NET Framework 4.0 provides built-in support for lazy initialization i.e. on-demand object initialization. If you want to make an object (such as Singleton) lazily initialized i.e. on-demand object initialization, then you just need to pass the type (Singleton) of the object to the Lazy generic class. And within the Lazy<T> constructor, using the lambda expression we need to create the instance which is shown below.

Lazy<Singleton> SingleInstance = new Lazy<Singleton>(() => new Singleton());

The most important point that you need to remember is the Lazy<T> objects are by default thread-safe. In a multi-threaded environment, when multiple threads are trying to access the same GetInstance Method at the same time, then the Lazy object will take care of thread safety. So, in order to use the Lazy Loading of the Singleton instance using the Lazy<T> generic class, please modify the Singleton class as follows. The following example code is self-explained, so please go through the comment lines for a better understanding.

using System;
namespace SingletonDemo
{
    public sealed class Singleton
    {
        //This variable value will be increment by 1 each time the object of the class is created
        private static int Counter = 0;

        //This will make the Singleton Instance Lazy Loading
        //Lazy Object are Thread-Safe by default
        private static readonly Lazy<Singleton> SingleInstance = new Lazy<Singleton>(() => new Singleton());

        //The following Static Method is going to return the Singleton Instance
        //This is Thread-Safe as it uses Lazy<T> Object
        public static Singleton GetInstance()
        {
            //Now we don't need to use any NULL Checking code
            //We don't need to write Explicit code for thread-safety
            //Call the Value property of the Lazy object which will return the Singleton Instance
            return SingleInstance.Value;
        }

        private Singleton()
        {
            //Each Time the Constructor is called, increment the Counter value by 1
            Counter++;
            Console.WriteLine("Counter Value " + Counter.ToString());
        }

        //The following method can be accessed from outside of the class by using the Singleton Instance
        public void PrintDetails(string message)
        {
            Console.WriteLine(message);
        }
    }
}

With the above changes in place, now run the application and see the output.

Example to Understand Lazy Loading of Singleton Instance using Lazy<T> Generic Class

 

 

We got the same output as Eager Loading. This is because of the lazy keyword which creates only one singleton instance and also they are by default thread-safe. This is the reason why we do not get any error while invoking the methods parallelly.

In the next article, I am going to discuss the Difference Between Static Class vs Singleton Class in C# with Examples. Here, in this article, I try to explain Lazy Loading vs Eager Loading in Singleton Design Patterns using C# with Examples. I hope this C# Lazy Loading and Eager Loading in the Singleton Design Pattern article will help you with your needs. I would like to have your feedback. Please post your feedback, question, or comments about this Lazy Loading vs Eager Loading in the Singleton Design Pattern article.

7 thoughts on “Lazy Loading vs Eager loading in Singleton Design Pattern”

  1. Abhishek Singh

    Thanks, one thing which is unique and best in your articles is, as soon a doubt/question comes in my mind after reading the article, at the bottom of your article you provide the link of that article :). I don’t need to go to any other tab to search the doubt/question.

    1. Hi, this is my personal experience. As a student and when I start learning programming, whatever problems I faced, I don’t want others to face the same problem. Thanks for finding our articles useful and also for giving your valuable feedback. This means a lot to us.

Leave a Reply

Your email address will not be published. Required fields are marked *