Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java Singleton with an inner class - what guarantees thread safety?

One common (1,2) way of implementing a singleton uses an inner class with a static member:

public class Singleton  {    
    private static class SingletonHolder {    
        public static final Singleton instance = new Singleton();
    }    

    public static Singleton getInstance() {    
        return SingletonHolder.instance;    
    }

    private Singleton() {
        //...
    }
}

This implementation is said to be lazily initialized and thread-safe. But what exactly guarantees its thread safety? JLS 17 that deals with Threads and Locks doesn't mention that static fields have any sort of happens-before relationship. How can I be sure that the initialization will only happen once and that all threads see the same instance?

like image 606
Malt Avatar asked Oct 03 '17 10:10

Malt


People also ask

How to implement a thread safe singleton class in Java?

2 Ways to implement a thread safe singleton class in java 5.1 Using static inner class 5.2 Using static initializer block The important concept behind the singleton design pattern is to have no more than one instance of the target class at any given time per java virtual machine.

What is singleton pattern in Java?

Java Singleton Pattern is one of the Gangs of Four Design patterns and comes in the Creational Design Pattern category. Singleton pattern restricts the instantiation of a class and ensures that only one instance of the class exists in the java virtual machine. The singleton class must provide a global access point to get the instance of the class.

Can Singleton be used in a single threaded environment?

It can be used in a single threaded environment because multiple threads can break singleton property because they can access get instance method simultaneously and create multiple objects. Object is created only if it is needed. It may overcome resource overcome and wastage of CPU time.

What happens when a singleton class is loaded in Java?

When the singleton class is loaded, inner class is not loaded and hence doesn’t create object when loading the class. Inner class is created only when getInstance () method is called. So it may seem like eager initialization but it is lazy initialization. This is the most widely used approach as it doesn’t use synchronization.


1 Answers

It's well described in Java Concurrency in Practice:

The lazy initialization holder class idiom uses a class whose only purpose is to initialize the Resource. The JVM defers initializing the ResourceHolder class until it is actually used [JLS 12.4.1], and because the Resource is initialized with a static initializer, no additional synchronization is needed. The first call to getresource by any thread causes ResourceHolder to be loaded and initialized, at which time the initialization of the Resource happens through the static initializer.

Static initialization

Static initializers are run by the JVM at class initialization time, after class loading but before the class is used by any thread. Because the JVM acquires a lock during initialization [JLS 12.4.2] and this lock is acquired by each thread at least once to ensure that the class has been loaded, memory writes made during static initialization are automatically visible to all threads. Thus statically initialized objects require no explicit synchronization either during construction or when being referenced.

like image 171
DDovzhenko Avatar answered Oct 21 '22 10:10

DDovzhenko