Mastering the Singleton Pattern in Java: Eager, Lazy, and Thread‑Safe Implementations

This article explains the concept of design patterns and dives deep into the Singleton pattern in Java, covering its purpose, eager and lazy implementations, thread‑safety challenges, double‑checked locking, volatile usage, static inner class, and enum approaches, while illustrating each with clear code examples and diagrams.

Java Backend Technology
Java Backend Technology
Java Backend Technology
Mastering the Singleton Pattern in Java: Eager, Lazy, and Thread‑Safe Implementations

Design patterns are reusable solutions to common software design problems; they improve code reusability, readability, and reliability.

Singleton Pattern

The Singleton ensures that a class has only one instance that is globally accessible, similar to how no two identical leaves exist on Earth.

There are two main categories:

Eager (饿汉) mode – the instance is created when the class is loaded.

Lazy (懒汉) mode – the instance is created upon first use.

Eager Mode

A basic implementation can be illustrated as follows:

This approach is simple but may waste resources if the instance is created too early, especially when the singleton consumes significant resources.

Class Loading Timing

When a new object is created.

When an instance is created via reflection.

When a subclass is loaded before its superclass.

When the JVM loads the main class at startup.

Lazy Mode

Typical lazy implementation:

If multiple threads call getInstance() simultaneously, both may see instance == null and create separate objects, breaking the singleton guarantee.

Adding synchronized to the method ensures only one thread can execute the critical section at a time:

While this prevents duplicate instances, it can degrade performance because all threads except the one holding the lock must wait.

Double‑Check Locking

To reduce synchronization overhead, double‑check locking adds two if (instance == null) checks:

The first check avoids entering the synchronized block when the instance already exists.

The second check ensures that only one thread creates the instance.

However, this pattern still suffers from issues related to atomicity and instruction reordering.

Atomic Operation

An atomic operation cannot be interrupted by thread scheduling. For example: m = 6; // atomic operation In contrast, a declaration with assignment is not atomic:

int n = 6; // not atomic

Instruction Reordering

Compilers may reorder independent statements to improve performance, e.g.:

int a;   // statement 1
a = 8;   // statement 2
int b = 9; // statement 3
int c = a + b; // statement 4

Execution order might become 3‑1‑2‑4 or 1‑3‑2‑4 without affecting the final result.

During singleton creation, the steps are:

Allocate memory for the instance.

Invoke the constructor to initialize fields.

Assign the reference to the variable.

Instruction reordering can swap steps 2 and 3, causing another thread to see a non‑null reference before the object is fully initialized, leading to errors.

The fix is to declare the instance variable as volatile, which prevents reordering of these steps:

Using volatile creates a memory barrier, ensuring that writes to the instance are completed before any read can occur.

Other Implementations

Static Inner Class

The inner class SingletonHolder is loaded lazily by the class loader, guaranteeing thread‑safe lazy initialization without explicit synchronization.

Enum

Enum singletons are simple, efficient, and inherently thread‑safe due to Java’s built‑in serialization mechanism.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

Javaenumthread safetydesign patternvolatileSingletonDouble-Check Locking
Java Backend Technology
Written by

Java Backend Technology

Focus on Java-related technologies: SSM, Spring ecosystem, microservices, MySQL, MyCat, clustering, distributed systems, middleware, Linux, networking, multithreading. Occasionally cover DevOps tools like Jenkins, Nexus, Docker, and ELK. Also share technical insights from time to time, committed to Java full-stack development!

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.