Ensuring thread safety in Java Singleton Classes

The Singleton design pattern is extensively employed to control object creation in applications. Ensuring thread safety for the singleton class is crucial when used in a multi-threaded environment. In real-world scenarios, it is essential to use limited resources like Database connections or Enterprise Information Systems (EIS) wisely in order to prevent any shortage. This can be accomplished by implementing a Singleton design pattern, which involves creating a wrapper class for the resource and restricting the number of objects created to just one during runtime.

Java’s Thread Safe Singleton

thread safe singleton in java
    To prevent the creation of new objects using the new operator, implement a private constructor. Define a private static instance of the class and offer a public static method that returns the instance variable of the singleton class. If the variable is not yet initialized, initialize it; otherwise, return the instance variable.

After following the aforementioned steps, I have successfully developed a singleton class known as ASingleton.java.

package com.scdev.designpatterns;

public class ASingleton {

	private static ASingleton instance = null;

	private ASingleton() {
	}

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

}

The getInstance() method in the provided code is not thread-safe, meaning that multiple threads can access it concurrently. When the instance variable is not yet initialized, the first few threads can enter the if loop simultaneously and generate multiple instances, which would undermine the implementation of our singleton.

What is the approach to ensure thread-safety in a Singleton Class?

We can accomplish thread safety in three different ways.

    One advantage is that the instance variable is created during the loading of the class.
  • Thread safety without synchronization
  • Easy to implement

Drawbacks:

  • 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. – Ensure thread safety in accessing the getInstance() method.

 

    1. – Prevent multiple threads from creating multiple instances of the object simultaneously.

 

    1. – Maintain consistency and avoid race conditions in multi-threaded environments.

 

    – Improve performance by reducing the overhead of unnecessary object creation.
  • Thread safety is guaranteed.
  • Client application can pass parameters
  • Lazy initialization achieved

Drawbacks:

  • Slow performance because of locking overhead.
  • Unnecessary synchronization that is not required once the instance variable is initialized.
    One advantage is that you can incorporate a synchronized block within the if loop and utilize a volatile variable.
  • 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.

Downsides:

  • Extra if condition

After considering all three methods for achieving thread-safety, I believe the third one is the optimal choice. Consequently, the modified class will have the following appearance:

package com.scdev.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 presence of the local variable result may appear unnecessary, but it serves to enhance the efficiency of our code. By using “return result;” instead of “return instance;”, the volatile field is accessed only once in cases where the instance is already initialized, which can boost the performance of the method by up to 25 percent. If you have alternative methods or concerns about the thread-safety of the above implementation, kindly share your thoughts for discussion.

Additional suggestion.

Using the synchronized keyword with a String is not ideal since Strings are stored in a pool and there is a risk of locking a String that is being used by another section of code. Instead, I am using an Object variable. Explore further about synchronization and ensuring thread safety in Java.

You can explore additional Java examples on our GitHub Repository.

 

More tutorials

multithreading in Java that you need to know(Opens in a new browser tab)

Java thread ensuring Java code is thread-safe(Opens in a new browser tab)

Strategy Design Pattern in Java tutorial(Opens in a new browser tab)

get pandas DataFrame from an API endpoint that lacks order?(Opens in a new browser tab)

Converting a Python string to an integer and vice versa.(Opens in a new browser tab)

 

Leave a Reply 0

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