Monday, January 18, 2016

Volatile real use

So there are two thing we can do with volatile in Java.

1. Declaring primitive volatile
2. Declaring object volatile

So lets see what happens with each when we declare it volatile.

1. Declaring primitive as volatile:-




Lets try to understand above diagram.
So in this we have declared two variable a and b as normal int but c as volatile int.
Then thread T1 writing to a then b and at the same time or some time difference thread t2 is reading a and b.
So T2 may read  0 or 7 for a and 0 or 8 for b. Because when T1 write to a and b it will first write that in its cache. But it is also possible, that value of a and b may also get pushed to main memory. But it is not guaranteed.

But when T1 reaches line c=9, and execute it, now it is guaranteed that other thread like T2 will see the changes now, that are done by T1. But it is conditional on that, they read value of volatile c first that is modified by T1.

So what are the rule that we can take out from above explanation.
1. When volatile write happens, every thing before this should be completed.
2. When read happens, reader thread will see who has changed(means different from earlier read) the value of volatile and that thread can see all the changes that are done by writer thread.

2. Declaring object volatile:-
 
Declaring object as volatile has the same impact as primitive.
1.  Means when writing to reference variable means assigning a object to it, all the instruction(As the object creation is divided into three parts) before it should be completed. And its value means the address to which this reference variable is pointing now, will be pushed to main memory .
2. And when reading a reference variable, read from main memory, means see if the reference variable is still pointing to the same object or not. If it is still pointing to the same object then reader thread may not notice any difference. Because according to rule 2 reader thread will see no difference in reference variable, as it is still pointing to same object(think of some numeric object address) so if any changes are done to non volatile member variable of that volatile reference variable it may not notice any difference.



So know we will have to understand what is stored in a reference variable. A reference variable just store the address of object.

Lets try to understand above diagram. In this thread T1 assign creates a new object and assign it to animal reference variable. So what gets store in animal reference variable is address 2000. And same value for reference variable.  Then in T2 thread it creates new object which has address 2002 and assign it same animal reference variable. So now think, when thread T1 want to change the value of animal name what it will do. It will first read the animal reference variable value and it will see that it having 2000 stored in its cache. So it will go to address 2000 and modify that object in the heap. It got the animal reference variable value 2000 from its cache only. As we were doing with primitive. But if it were went to main memory also, there is no guarantee it will 2002 as value of animal reference variable because it may also happen that T2 may have written it in its cache only. So main memory will still have 2000 as the value of animal reference variable.

Solution to above problem is declare the animal reference variable volatile. So any thread will read or write to animal reference variable it will always go to main memory.So both will see value of animal refernce variable as 2002.

Lets elaborate point 1 little bit.
Declaring an object volatile has some advantage when we are creating an object and do not want partially initialized object to be used by other thread.

Actually creation of an object is 3 step statement. So when execute below statement 3 things happens

class Animal{
private String name = "Some Name";
}

volatile Animal animal = new Animal();

So when above statement is executed three things happens. They should be executed in the same order but for performance reason processor may choose to execute it in different order.

a. Memory Allocation
b. Memory Initialization
c. Reference assignment

So if we don't declare animal object as volatile it can follow below execution.
a -> c ->b

So think a->c has been executed in thread T1 but not b, and other thread T2 now may see animal has been assigned. So it can see partially initialized object.
So for stopping such kind of behavior we should declare it volatile. So in that case when c instruction comes for execution, processor will see that it should complete a and b instruction before executing c. So it will complete instruction a and b.  Then when c instruction is executed which assigning to a volatile variable.
When some other thread comes and read that volatile refenece variable it will see it have been changed, so it will see all the changes till now whatever is done by thread T1

These above guarantee is provided by JMM. So JMM is responsible for providing these semantics. They may be using some processor level instruction to implement these semantics.

So the only use of volatile is to provide these semantics only. That is it.

So to conclude declaring refence varialbe as volatile gives us.
1. Uninitialiezed object will not skip.
2. Reference variable will always point to correct object.



But we some time misunderstand it, and gets confuse and think that if we declare an object volatile so its all member variables will have updted value.

Declaring an object as volatile does not have to do anything with its member variable.It does not provide any kind of protection for those varialble.



 
















No comments:

Post a Comment