What is Lazy instantiation?
With lazy instantiation, a program refrains from creating certain resources until the resource is first needed — freeing valuable memory space. One solution is
using synchronized method getInstance(). The problem is the method called every time, while synchronization is actually needed only for the first call of the method (which introduces performance overhead in your application).
There were attempts to tackle this problem by using Double-checked locking pattern (DCL).

Lazy instantiation

What is Double-checked locking (DCL)?
The DCL idiom was designed to support lazy initialization, which occurs when a class defers initialization of an owned object until it is actually needed.
Unfortunatelly we found “Double-Checked Locking is Broken”.

The “Double-Checked Locking is Broken” Declaration
Double-checked locking: Clever, but broken

Alternatives to DCL
The most effective way to fix the DCL idiom is to avoid it. The simplest way to avoid it, of course, is to use synchronization. Whenever a variable written by one thread is being read by another, you should use synchronization to guarantee that modifications are visible to other threads in a predictable manner.

Another option for avoiding the problems with DCL is to drop lazy initialization and instead use eager initialization. Rather than delay initialization of resource until it is first used, initialize it at construction. The class loader, which synchronizes on the classes’ Class object, executes static initializer blocks at class initialization time. That means that the effect of static initializers is automatically visible to all threads as soon as the class loads.

One special case of lazy initialization that does work as expected without synchronization is the static singleton. When the initialized object is a static field of a class with no other methods or fields, the JVM effectively performs lazy initialization automatically.

What is Singleton pattern?
The singleton pattern is implemented by creating a class with a method that creates a new instance of the class if one does not exist. If an instance already exists, it simply returns a reference to that object. To make sure that the object cannot be instantiated any other way, the constructor is made either private or protected.

Wiki: Singleton pattern

What is Stateful Singleton?
We can use ThreadLocal to implement a per-thread Singleton to render stateful Singleton or shared objects thread-safe. This is most used at multiple threads application which want to keep each thread has own non-shared resource like JDBC connection.

Improve Thread Local Pattern
Threads Versus The Singleton Pattern