Tutorial

Thread Safety in Java Singleton Classes

Published on August 3, 2022
Default avatar

By Pankaj

Thread Safety in Java Singleton Classes

While we believe that this content benefits our community, we have not yet thoroughly reviewed it. If you have any suggestions for improvements, please let us know by clicking the “report an issue“ button at the bottom of the tutorial.

Singleton is one of the most widely used creational design pattern to restrict the object created by applications. If you are using it in a multi-threaded environment, then the thread-safety of the singleton class is very important. In real-world applications, resources like Database connections or Enterprise Information Systems (EIS) are limited and should be used wisely to avoid any resource crunch. To achieve this, we can implement a Singleton design pattern. We can create a wrapper class for the resource and limit the number of objects created at runtime to one.

Thread Safe Singleton in Java

thread safe singleton in java In general, we follow the below steps to create a singleton class:

  1. Create the private constructor to avoid any new object creation with new operator.
  2. Declare a private static instance of the same class.
  3. Provide a public static method that will return the singleton class instance variable. If the variable is not initialized then initialize it or else simply return the instance variable.

Using the above steps I have created a singleton class that looks like below. ASingleton.java

package com.journaldev.designpatterns;

public class ASingleton {

	private static ASingleton instance = null;

	private ASingleton() {
	}

	public static ASingleton getInstance() {
		if (instance == null) {
			instance = new ASingleton();
		}
		return instance;
	}

}

In the above code, the getInstance() method is not thread-safe. Multiple threads can access it at the same time. For the first few threads when the instance variable is not initialized, multiple threads can enter the if loop and create multiple instances. It will break our singleton implementation.

How to achieve thread-safety in Singleton Class?

There are three ways through which we can achieve thread safety.

  1. Create the instance variable at the time of class loading. Pros:
  • Thread safety without synchronization
  • Easy to implement

Cons:

  • Early creation of resource that might not be used in the application.
  • The client application can’t pass any argument, so we can’t reuse it. For example, having a generic singleton class for database connection where client application supplies database server properties.
  1. Synchronize the getInstance() method. Pros:
  • Thread safety is guaranteed.
  • Client application can pass parameters
  • Lazy initialization achieved

Cons:

  • Slow performance because of locking overhead.
  • Unnecessary synchronization that is not required once the instance variable is initialized.
  1. Use synchronized block inside the if loop and volatile variable Pros:
  • Thread safety is guaranteed
  • Client application can pass arguments
  • Lazy initialization achieved
  • Synchronization overhead is minimal and applicable only for first few threads when the variable is null.

Cons:

  • Extra if condition

Looking at all the three ways to achieve thread-safety, I think the third one is the best option. In that case, the modified class will look like this:

package com.journaldev.designpatterns;

public class ASingleton {

	private static volatile ASingleton instance;
	private static Object mutex = new Object();

	private ASingleton() {
	}

	public static ASingleton getInstance() {
		ASingleton result = instance;
		if (result == null) {
			synchronized (mutex) {
				result = instance;
				if (result == null)
					instance = result = new ASingleton();
			}
		}
		return result;
	}

}

The local variable result seems unnecessary. But, it’s there to improve the performance of our code. In cases where the instance is already initialized (most of the time), the volatile field is only accessed once (due to “return result;” instead of “return instance;”). This can improve the method’s overall performance by as much as 25 percent. If you think there are better ways to achieve this or if the thread-safety is compromised in the above implementation, please comment and share it with all of us.

Bonus Tip

String is not a very good candidate to be used with synchronized keyword. It’s because they are stored in a string pool and we don’t want to lock a string that might be getting used by another piece of code. So I am using an Object variable. Learn more about synchronization and thread safety in java.

You can checkout more Java examples from our GitHub Repository.

Thanks for learning with the DigitalOcean Community. Check out our offerings for compute, storage, networking, and managed databases.

Learn more about us


About the authors
Default avatar
Pankaj

author

Still looking for an answer?

Ask a questionSearch for more help

Was this helpful?
 
JournalDev
DigitalOcean Employee
DigitalOcean Employee badge
June 20, 2021

Hi, I did not understood the use of result variable, and how it is helping in improve performance by 25%

- sakshi

    JournalDev
    DigitalOcean Employee
    DigitalOcean Employee badge
    June 11, 2021

    What is the use of mutex Object here sir i cannot understand.

    - Sagar Solanki

      JournalDev
      DigitalOcean Employee
      DigitalOcean Employee badge
      June 3, 2020

      I didn’t understand this part “Local variable result seems unnecessary” and the explanation you gave. Could you elaborate please?

      - Kshitiz Gupta

        JournalDev
        DigitalOcean Employee
        DigitalOcean Employee badge
        May 12, 2019

        Isn’t static inner helper class approach better than the above three mentioned?

        - Pallavi Singh

          JournalDev
          DigitalOcean Employee
          DigitalOcean Employee badge
          December 18, 2018

          Hi Pankaj, How to execute your Singleton class. Where is the main method ? Deepak

          - Deepak

            JournalDev
            DigitalOcean Employee
            DigitalOcean Employee badge
            September 5, 2018

            Hey Nice Solution but i think we can also optimize is by not creating object lock instead of it we can use class lock example Copied! package com.journaldev.designpatterns; public class ASingleton { private static volatile ASingleton instance; private ASingleton() { } public static ASingleton getInstance() { ASingleton result = instance; if (result == null) { synchronized (ASingleton.class) { result = instance; if (result == null) instance = result = new ASingleton(); } } return result; } } I am not sure Please guide me as i am fresher

            - Harshit Joshi

              JournalDev
              DigitalOcean Employee
              DigitalOcean Employee badge
              September 2, 2018

              This seems ok…create instance on class loading and later return same instance…No synchronization required. public class Singleton { private static Singleton singltonInstance = new Singleton(); private Singleton() { } public static Singleton getInstance() { return singltonInstance; } @Override protected Object clone() throws CloneNotSupportedException { throw new CloneNotSupportedException(); } }

              - Datta

                JournalDev
                DigitalOcean Employee
                DigitalOcean Employee badge
                June 26, 2018

                You don’t talk about enum. Enum objects are best suited for singleton classes. It covers both concurrency and serialization issues we face in our custom singleton classes.

                - jatin

                  JournalDev
                  DigitalOcean Employee
                  DigitalOcean Employee badge
                  May 2, 2018

                  public class TestSingleton { public static void main(String[] args) throws NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { ASingleton singleton1 = ASingleton.getInstance(); System.out.println(singleton1); ASingleton singleton2 = ASingleton.getInstance(); System.out.println(singleton2); Constructor c = ASingleton.class.getDeclaredConstructor((Class[]) null); c.setAccessible(true); System.out.println©; ASingleton singleton3 = c.newInstance((Object[]) null); System.out.println(singleton3); if (singleton1 == singleton2) { System.out.println(“Variable 1 and 2 referes same instance”); } else { System.out.println(“Variable 1 and 2 referes different instances”); } if (singleton1 == singleton3) { System.out.println(“Variable 1 and 3 referes same instance”); } else { System.out.println(“Variable 1 and 3 referes different instances”); } } } Hi Pankaj, NIce article, but the solution you provided , fails the above testcase. Thanks .

                  - ashish gupta

                    JournalDev
                    DigitalOcean Employee
                    DigitalOcean Employee badge
                    April 29, 2018

                    The third option is not a singlton class it will create new instance always.

                    - Parvesh Kumar

                      Try DigitalOcean for free

                      Click below to sign up and get $200 of credit to try our products over 60 days!

                      Sign up

                      Join the Tech Talk
                      Success! Thank you! Please check your email for further details.

                      Please complete your information!

                      Get our biweekly newsletter

                      Sign up for Infrastructure as a Newsletter.

                      Hollie's Hub for Good

                      Working on improving health and education, reducing inequality, and spurring economic growth? We'd like to help.

                      Become a contributor

                      Get paid to write technical tutorials and select a tech-focused charity to receive a matching donation.

                      Welcome to the developer cloud

                      DigitalOcean makes it simple to launch in the cloud and scale up as you grow — whether you're running one virtual machine or ten thousand.

                      Learn more
                      DigitalOcean Cloud Control Panel