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.
In general, we follow the below steps to create a singleton class:
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.
There are three ways through which we can achieve thread safety.
Cons:
Cons:
Cons:
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.
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.
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.
Sign up for Infrastructure as a Newsletter.
Working on improving health and education, reducing inequality, and spurring economic growth? We'd like to help.
Get paid to write technical tutorials and select a tech-focused charity to receive a matching donation.
Hi, I did not understood the use of result variable, and how it is helping in improve performance by 25%
- sakshi
What is the use of mutex Object here sir i cannot understand.
- Sagar Solanki
I didn’t understand this part “Local variable result seems unnecessary” and the explanation you gave. Could you elaborate please?
- Kshitiz Gupta
Isn’t static inner helper class approach better than the above three mentioned?
- Pallavi Singh
Hi Pankaj, How to execute your Singleton class. Where is the main method ? Deepak
- Deepak
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
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
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
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
The third option is not a singlton class it will create new instance always.
- Parvesh Kumar