Example:
class Something{ private volatile static Something instance = null; private int x; private int y; private Something(){ this.x = 1; this.y = 2; } public static Something getInstance() { if (instance == null) { synchronized (Something.class) { if (instance == null) instance = new Something(); } } } return instance; } }
Explanation:
Let's say we have the code above:
Now suppose the instance is unstable for some time:
Theme number 1:
The getInstance method comes to invoke, checks the value of the {{zero} instance, enters the IF condition, Access Lock now again detects that the instance == null, calls the constructor something. Now it goes inside the body of the constructor.
As soon as Thread # 1 enters the body of the constructor, Context Switch occurs, and now Thread # 2 gets a move to execute.
Theme number 2:
Invokes get Instance, but suddenly discovers that the instance is not null? Why {Reason will be discussed only after this} and, therefore, assign a partially constructed object to the link and return it.
Now the situation is as follows: Thread # 1 You still need to build an Object Completely (you need to completely build it), and Thread # 2 got a link to a partially constructed Object, and if it uses it, like reference.x // will print "x "Default value, not" 1 "
Why is a partially constructed object reference returned in the case of Thread # 2? The reason is simple: Regulation of expressions . The steps are easy to create an object and a link:
- Allocate memory in a heap.
- Run the body of the constructor that initializes the members of the class.
- Upon completion of the above Step, a link to the newly created object.
But sometimes the compiler can execute these instructions out of order , which means:
This could happen something like this:
- Allocate memory in a heap.
- Link to the newly created object.
- Run the body of the constructor that initializes the members of the class.
As soon as the previous two steps have occurred, and if the context switch occurs, the link refers to an Object that is not initialized, or it may be that inside the context switch Body Constructor occurs when the link refers to a partially initialized object.
If such a scenario occurs, the link will be neither null nor complete, and therefore it will violate our Singleton motivation.
Now that Volatile will save our Life from such embarrassment:
As we know, volatile work with two principles: 1) Visibility 2) It happens before a relationship . Now happens before contact .
Thus, the reference is volatile Write, so all statements must be executed before any volatile write.Again. If we look at our stages of building an object:
- Allocate memory for an object
- Initialize member variables {constructor body}
- Assign an object reference to an instance of a mutable variable.
Step 3 has Volatile Variable write and, as before. All message records are guaranteed to be available for step 3. And since it is unstable, therefore, permutations will not change between volatile and non-volatile operators, which was not in the Java memory model. Thus, before performing step 3, steps 1 and 2 are guaranteed to be performed and become available for step 3. {In what order are steps 1 and 2 performed, we donβt worry about that.}
So, from this stream you will see either a Completely created object or null