There is such a singleton implementation based on double checked locking ( item 2 ):

public class Singleton { private static volatile Singleton instance; public static Singleton getInstance() { Singleton localInstance = instance; if (localInstance == null) { synchronized (Singleton.class) { localInstance = instance; if (localInstance == null) { instance = localInstance = new Singleton(); } } } return localInstance; } } 

Question 1: What is localInstance used localInstance ? Why not do this:

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

?

I have an assumption: reading a volatile field is a bit more expensive than reading a regular field or a local variable, which is why a local variable is used here. If I am right and someone can paint this moment in more detail - I would be grateful.

Question 2: Why is a private constructor not declared in this class? Indeed, in the absence of it somewhere in the code, you can explicitly create an instance of this class.

  • Regarding the second question, there is a link to the previous article, in which everything is described. In this decided not to write the obvious (for granted). - vp_arth
  • By the way, pay attention to the fifth version of the same previous article - vp_arth
  • @Burence my answer is not correct, please remove the label, I will delete it, so as not to mislead people - Artem Konovalov

2 answers 2

This is done, partly because of performance, partly because if the additional local variable is not used, the code may not work correctly.

Namely, if we write in synchronized :

 instance = new Singleton(); 

And Singleton will have, for example, the following structure:

 class Singleton { private Object obj; Singleton(){ obj = new Object(); } } 

That, the compiler can the designer, thus without keeping an order of operations. Those. the following may happen:

  1. Singleton object is created
  2. Assigned to instance
  3. Fields in created object are initialized.

This situation is called unsafe publication . To fix it enough, define the fields either final or volatile (there are more options).

Good article with examples on this topic.

Ps. Anyone interested, you can run the jsctress test and play with different variations.

  • Did you manage to reproduce the problem with a not fully initialized object? I am with a good hour at this ditched, but all in vain. Either my incorrect test comes out, or it takes longer and more testing, or it should be done not on my computer, or it is irrelevant now. - Regent
  • Under unsafe publication is meant a situation where the second thread sees that instance != null , but at the same time the instance itself is not yet completely initialized at this moment? - Burence
  • @Burence is exactly like this when the field object is not fully initialized yet. - Artem Konovalov
  • @Regent may well be that for a specific platform and will not be played, but java is not limited to only x86 or x64 - Artem Konovalov

localInstance needed to improve the performance of this code.

In cases where the instance has already been initialized (i.e. in most cases)
this allows you to not access the volatile field a second time,
with return instance instead of return localInstance

Source: Joshua Bloch "Effective Java, Second Edition", p. 283-284
There he claims that this allows for a 25% increase in productivity.


Regarding the second question - I believe that a private constructor in a singleton is a matter of course.
Therefore, when discussing deeper implementation details, it is permissible to omit this point.