Search This Blog

Saturday, 26 October 2013

Understanding volatile

Before I start - I have never used volatile nor can I claim to well versed at it. To be more accurate my understanding of the java volatile keyword is zilch. Part of the reason is that I never used it. Did not use hence did not bother learning.
So to understand the concept I searched the net. I found articles where explanations where given. These articles were then followed by comments claiming that the explanation was wrong/incomplete. Some of the posts only managed to confuse me further.
So when I found something that made sense, I decided to jot it down...........
Volatile is concerned with change. Not any change. Change by some external process. A change that happened without our awareness.
In Java, the best place to see such changes is a multi-threaded program. And not just the bad ones. These changes (or errors) occur when different threads have varying views of what should be the same data. For example a shared global variable being accessed and modified by multiple threads. The end result is always going to be inconsistent.
To ensure we do not encounter these pitfalls we have what is known as the "happens-before relationship".
From Wikipedia:
In Java specifically, a happens-before relationship is a guarantee that memory written to by statement A is visible to statement B, i.e. statement A completes its write before statement B starts its read.
This kind of behavior is guaranteed with synchronization.
If thread B were to try and invoke a synchronized method after Thread A, it is guaranteed to be aware of all changes made by Thread A. The state of the object are visible to all threads.
Similarly:
  • When a statement invokes Thread.start, every statement that has a happens-before relationship with that statement also has a happens-before relationship with every statement executed by the new thread. The effects of the code that led up to the creation of the new thread are visible to the new thread. 
  • When a thread terminates and causes a Thread.join in another thread to return, then all the statements executed by the terminated thread have a happens-before relationship with all the statements following the successful join. The effects of the code in the thread are now visible to the thread that performed the join. 
While this explains the working of synchronized and threads what about volatile ??
Writing to a volatile variable is also an example of the "happens-before relationship".
Thus if a thread B were to update a volatile variable, its changes would be visible to all other threads that then tried to read it.
But then could we not have achieved the same by synchronizing the read/write methods ? Is volatile same as synchronize ?
This site answers the above question beautifully, stated below:
Each thread has its own stack, and so its own copy of variables it can access. 
When the thread is created, it copies the value of all accessible variables in 
its own memory. The volatile keyword is used to say to the jvm “Warning, this 
variable may be modified in an other Thread”. Without this keyword the JVM is 
free to make some optimizations, like never refreshing those local copies in some 
threads. The volatile force the thread to update the original variable for each variable. 
The volatile keyword could be used on every kind of variable, either primitive or objects!
As seen above the presence of a volatile keyword is one way of telling threads that the value of the variable must be read from the main heap.
The synchronized keyword ensures that the execution of a certain set of java statements are done in a mutually exclusive manner. Thus any data changes caused by these statements remain thread safe.
Volatile is necessary to ensure that threads are aware of any shared variable  they are accessing. This ensures that they work with the latest value in memory and not any local copies. 
I guess if a memory location could be synchronized then we probably wouldn't have volatile.

The "happens before relationship" also ensures that when a thread reads a volatile variable, it sees not just the latest change to the volatile, but also the side effects of the code that led up the change. This is what makes it seem similar to synchronization.

An additional feature enjoyed by volatile variables is atomic access. Or an action that either happens or does not happen. No midway behavior. (Like the A in ACID properties of database transactions.)
This feature is made clearer when we consider operations like increment operator.
This single java operation in machine language would be equivalent to several instructions. For volatile keywords these instructions would never be interfered or reordered by the compiler in its attempt to optimize execution. They would be treated as one single unit.
Similarly for a long or double when the data would actually span several words and hence a read would be again multiple instructions. Volatile ensures that the memory read for such variables is treated as an atomic operation.

As seen volatile unlike synchronized may not something whose impact is explicit to a coder. As I am yet to encounter any real scenarios related to volatile, my understanding too may be incomplete (sigh).
Do comment if you have anything to add. Anything to make my understanding of this topic non-volatile !

No comments:

Post a Comment