2

How below 2 codes are different in terms of multithreaded environment?

Code 1:

public class Singleton { private Singleton() {} private static class SingletonHolder { private static final Singleton INSTANCE = new Singleton(); } public static Singleton getInstance() { return SingletonHolder.INSTANCE; } } 

Code 2:

class Singleton { private static Singleton uniqueInstance; private Singleton() { ... } public static Singleton getInstance() { if (uniqueInstance == null) { uniqueInstance = new Singleton(); } return uniqueInstance; } } 

Why Code 2 will not work in multi threaded environment, when it has also static variable declared which will get loaded once class is loaded & thus it'll have only one instance?

Thanks!

2 Answers 2

4

Remember that more than one thread can call getInstance at a given time.

In Example 1, the initializer for the uniqueInstance member is guaranteed to be only run once - at class load time.

In Example 2, since initialization takes place inline in getInstance, more than one thread can independently and concurrently find the uniqueInstance member variable to be null. Each thread will then call new Singleton(), with indeterminate results that depend on the timing of the two (or more) threads.

For Example 2 to work, you could (for example) add synchronized on the getInstance method.

Your comment about the variable being fully initialized at class load time is true for Example 1, but not for 2 - in example 2 the member variable is set to null at class load time, but populated with an object instance later, during the first call(s) to getInstance.

Sign up to request clarification or add additional context in comments.

5 Comments

What if I remove null check condition from Example 2? In that case, when multiple thread will try to call getInstance(), it'll see that 1st thread has already initialized it, right? Then, why we say that Example 2 is not thread safe?
That will make things worse, because then every user of the singleton will get their own instance of the class. The check is required, but has to be made in a thread-safe way, typically using synchronized.
But I declared it as static & isn't static supposed to load only once?
Correct. The reason Example 1 works properly is because you couple load time to member initialization. In Example 2 member initialization is coupled to "the first call" to getInstance. Problem is, in multithreaded config, "the first call" to a function is meaningless, without synchronization to enforce a winner among concurrent candidates (threads) making "the first call".
It might be more proper to say that final is loaded only once, as I can initialize a static variable as many times I want. static only marks the variable as being shared between all instances of the class.
1

Multiple threads may be inside of the:

if (uniqueInstance == null) { ... } 

condition simultaneously.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.