đź“…Week-2 (Day 5) - Understanding the Singleton Design Pattern: Thread-Safe, Lazy, and Eager Initialization Explained

Table of contents
- đź’ What is Singleton Design Pattern?
- đź’ How Singleton Works Behind The Scenes?
- đź’ Step-by-Step: How to Implement Singleton in C++ & Java
- đź’ Lazy vs Eager Initialization
- đź’ Thread-Safe Singleton (Right Way to Do It)
- đź’ Real-World Use Cases of Singleton
- 💠Where NOT to Use Singleton ❌
- đź’ Common Pitfalls & Bottlenecks (Quick Summary)
- đź’ How to Avoid These Problems?

NOTE: - I started my 8-week system design journey with Coder Army. I will be journaling every day, recording what I learn, reflecting on it, and sharing it with my network to help newcomers to system design.
đź’ What is Singleton Design Pattern?
The Singleton Pattern ensures that a class can have only one object (instance) in the system — and gives a global point of access to it.
(Hindi : "Ek aisi class jo sirf ek baar object banaye, aur agar dubara object banane ki koshish karo, toh wahi pehla object return kare!" )
📍 Real-Life Analogy:
Imagine you have a Government ID Generator. You can have only one Aadhaar Card linked to you. If you try to make another, the system just refers back to your original Aadhaar. Same logic!
đź’ How Singleton Works Behind The Scenes?
A computer memory has two parts:
Heap – For storing objects (non-primitive data like custom classes)
Stack – For storing primitive types (int, char) and function calls
When we create an object like this:
A a = new A();
It's stored in the heap. But if you keep writing:
A a = new A(); A a2 = new A(); A a3 = new A();
Multiple objects are created. To prevent this, Singleton restricts object creation using a private constructor and returns the same instance using a method called
getInstance()
.
đź’ Step-by-Step: How to Implement Singleton in C++ & Java
âś… General Rules:
Private Constructor – To prevent outside object creation.
Static Instance – Stores the single instance.
Static Method (getInstance) – Returns that one instance.
class Singleton {
private:
static Singleton* instance;
Singleton() {} // Private constructor
public:
static Singleton* getInstance() {
if (!instance)
instance = new Singleton();
return instance;
}
};
// Define and initialize the static member
Singleton* Singleton::instance = nullptr;
public class Singleton {
private static Singleton instance;
private Singleton() {} // Private constructor
public static Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
NoSingleton
public class NoSingleton { public NoSingleton() { System.out.println("Singleton Constructor called. New Object created."); } public static void main(String[] args) { NoSingleton s1 = new NoSingleton(); NoSingleton s2 = new NoSingleton(); System.out.println(s1 == s2); } }
SimpleSingleton
public class SimpleSingleton {
private static SimpleSingleton instance = null;
private SimpleSingleton() {
System.out.println("Singleton Constructor called");
}
public static SimpleSingleton getInstance() {
if (instance == null) {
instance = new SimpleSingleton();
}
return instance;
}
public static void main(String[] args) {
SimpleSingleton s1 = SimpleSingleton.getInstance();
SimpleSingleton s2 = SimpleSingleton.getInstance();
System.out.println(s1 == s2);
}
}
- ThreadSafeDoubleLockingSingleton
public class ThreadSafeDoubleLockingSingleton {
private static ThreadSafeDoubleLockingSingleton instance = null;
private ThreadSafeDoubleLockingSingleton() {
System.out.println("Singleton Constructor Called!");
}
// Double check locking..
public static ThreadSafeDoubleLockingSingleton getInstance() {
if (instance == null) { // First check (no locking)
synchronized (ThreadSafeDoubleLockingSingleton.class) { // Lock only if needed
if (instance == null) { // Second check (after acquiring lock)
instance = new ThreadSafeDoubleLockingSingleton();
}
}
}
return instance;
}
public static void main(String[] args) {
ThreadSafeDoubleLockingSingleton s1 = ThreadSafeDoubleLockingSingleton.getInstance();
ThreadSafeDoubleLockingSingleton s2 = ThreadSafeDoubleLockingSingleton.getInstance();
System.out.println(s1 == s2);
}
}
- ThreadSafeEagerSingleton
public class ThreadSafeEagerSingleton {
private static ThreadSafeEagerSingleton instance = new ThreadSafeEagerSingleton();
private ThreadSafeEagerSingleton() {
System.out.println("Singleton Constructor Called!");
}
public static ThreadSafeEagerSingleton getInstance() {
return instance;
}
public static void main(String[] args) {
ThreadSafeEagerSingleton s1 = ThreadSafeEagerSingleton.getInstance();
ThreadSafeEagerSingleton s2 = ThreadSafeEagerSingleton.getInstance();
System.out.println(s1 == s2);
}
}
ThreadSafeLockingSingleton
public class ThreadSafeLockingSingleton { private static ThreadSafeLockingSingleton instance = null; private ThreadSafeLockingSingleton() { System.out.println("Singleton Constructor Called!"); } public static ThreadSafeLockingSingleton getInstance() { synchronized (ThreadSafeLockingSingleton.class) { // Lock for thread safety if (instance == null) { instance = new ThreadSafeLockingSingleton(); } return instance; } } public static void main(String[] args) { ThreadSafeLockingSingleton s1 = ThreadSafeLockingSingleton.getInstance(); ThreadSafeLockingSingleton s2 = ThreadSafeLockingSingleton.getInstance(); System.out.println(s1 == s2); } }
đź’ Lazy vs Eager Initialization
1) Lazy Initialization
Object is created only when needed.
🟢 Advantage: Saves memory
đź”´ Disadvantage: Not thread-safe by default
2) Eager Initialization
Object is created at the time of class loading.
🟢 Advantage: Simple and thread-safe
đź”´ Disadvantage: If object is heavy, it wastes memory.
📍 Tip:
“Eager tabhi use karo jab object lightweight ho. Agar object expensive hai, lazy better hai!”
đź’ Thread-Safe Singleton (Right Way to Do It)
In a multi-threaded environment, multiple threads can create multiple instances in lazy mode.
To fix this, we use:
1. Thread Safe with Synchronized (Java)
public synchronized static Singleton getInstance() {
if (instance == null)
instance = new Singleton();
return instance;
}
2. Double Checked Locking (Efficient)
public static Singleton getInstance() {
if (instance == null) {
synchronized (Singleton.class) {
if (instance == null)
instance = new Singleton();
}
}
return instance;
}
đź’ Real-World Use Cases of Singleton
1. Logging Systems
Only one instance logs all the errors or info.
2. Database Connections
One database object avoids unnecessary multiple DB connections.
3. Configuration Manager
All modules use the same config settings.
4. Cache or Memory Management
One central point to manage caching
💠Where NOT to Use Singleton ❌
In gaming apps, where each player needs their own object.
When you need multiple independent instances.
In unit tests, where singletons might introduce global state issues.
📍*“Jahaan pe har object ka alag behavior ho, wahan Singleton avoid karo.”*
đź’ Common Pitfalls & Bottlenecks (Quick Summary)
Global State:
Singleton acts as a global object – changes in one place affect everywhere. Hard to manage & test.Tight Coupling:
Code gets tightly connected with the Singleton – hard to modify or replace components later.Concurrency Issues:
Without proper thread-safety, Singleton can cause race conditions in multithreaded apps.Testing Challenges:
Singletons make unit testing difficult due to shared global state across tests.Hidden Dependencies:
Dependencies on Singleton are often unclear – making the code harder to maintain.Limited Extensibility:
Difficult to subclass or extend a Singleton class.Performance Bottlenecks:
Lazy loading can delay the first access; heavy objects waste memory in eager initialization.
Scalability Problems:
Managing Singleton across multiple threads/servers becomes tricky in large-scale systems.
đź’ How to Avoid These Problems?
Use Dependency Injection instead of global access
Prefer IoC Containers (e.g., Spring)
Always implement thread-safe Singleton
Consider alternatives like Factory or Service classes
"Ek ghar ka ek hi raja hota hai. Waise hi system ka ek hi singleton instance hona chahiye!" đź‘‘
Week - 2 (Day 5) Completed âś… System Design
NOTE : - A big thanks to my mentors Rohit Negi Sir and Aditya Sir for launching this amazing 8-week course absolutely free on YouTube via CoderArmy9 :- youtube.com/@CoderArmy9 . 🙌
👉 Share this blog with your connections! Let’s keep learning, growing, and supporting one another on this journey. 🚀
✍️ Payal Kumari 👩‍💻 Github
Jai Hind 🇮🇳 | #CoderArmy #LearningInPublic #SystemDesign #TechForAll #MentorshipMatters #8weeksLLdChallenge #LowLevelDesign #LLD 👩‍💻
Subscribe to my newsletter
Read articles from Payal Kumari directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by

Payal Kumari
Payal Kumari
I'm a passionate full-stack developer with a strong foundation in the MERN stack—building and maintaining scalable web applications using React.js, Node.js, and Next.js. My journey in open source began with Hacktoberfest 2023, where I made four impactful pull requests that sparked a love for collaborative coding, global learning, and open knowledge sharing. Since then, I’ve contributed to and mentored projects in top open source programs like GSSoC’24, SSOC’24, and C4GT’24. As a Google Gen AI Exchange Hackathon ’24 Finalist and Google’s Women Techmakers (WTM) Ambassador, I’ve been privileged to support diverse communities in building meaningful tech solutions. My work as a Top 50 Mentor for GSSoC ’24 reflects my commitment to nurturing new talent in tech. Beyond development, I serve as a Student Career Guide, Profile Building Expert & Evangelist at Topmate.io, where I conduct workshops, guide students through resume building and career strategy, and help mentees navigate open source and tech careers. Recognized among the Top 5% of mentors and featured on “Topmate Discover,” I take pride in making mentorship accessible and impactful. My technical voice has also been acknowledged by LinkedIn, where I’ve earned the Top Voice badge seven times in domains like web development, programming, and software engineering. In addition, I hold LinkedIn Golden Badges for Research Skills, Interpersonal Skills, Critical Thinking, and Teamwork—signaling a well-rounded approach to both individual contribution and team collaboration. Graduating with an MCA from Chandigarh University in 2023, I’ve continued to fuel my curiosity by writing technical articles and sharing practical MERN stack insights across platforms. Whether it’s building polished UIs, optimizing backend performance, or guiding a mentee through their first pull request, I’m driven by the power of community and continuous learning. Let’s connect! I'm open to collaborations, mentorship, or building something impactful together. Reach out to me at kumaripayal7488@gmail.com or visit my profile on Topmate.io.