At work today, I came across the volatile
keyword in Java. Not being very familiar with it, I found this explanation.
Given the detail in which that arti
Important point about volatile
:
synchronized
and volatile
and locks.synchronized
variable. Using synchronized
keyword with a variable is illegal and will result in compilation error. Instead of using the synchronized
variable in Java, you can use the java volatile
variable, which will instruct JVM threads to read the value of volatile
variable from main memory and don’t cache it locally.volatile
keyword.source
Example usage of volatile
:
public class Singleton {
private static volatile Singleton _instance; // volatile variable
public static Singleton getInstance() {
if (_instance == null) {
synchronized (Singleton.class) {
if (_instance == null)
_instance = new Singleton();
}
}
return _instance;
}
}
We are creating instance lazily at the time the first request comes.
If we do not make the _instance
variable volatile
then the Thread which is creating the instance of Singleton
is not able to communicate to the other thread. So if Thread A is creating Singleton instance and just after creation, the CPU corrupts etc, all other threads will not be able to see the value of _instance
as not null and they will believe it is still assigned null.
Why does this happen? Because reader threads are not doing any locking and until the writer thread comes out of a synchronized block, the memory will not be synchronized and value of _instance
will not be updated in main memory. With the Volatile keyword in Java, this is handled by Java itself and such updates will be visible by all reader threads.
Conclusion:
volatile
keyword is also used to communicate the content of memory between threads.
Example usage of without volatile:
public class Singleton{
private static Singleton _instance; //without volatile variable
public static Singleton getInstance(){
if(_instance == null){
synchronized(Singleton.class){
if(_instance == null) _instance = new Singleton();
}
}
return _instance;
}
The code above is not thread-safe. Although it checks the value of instance once again within the synchronized block (for performance reasons), the JIT compiler can rearrange the bytecode in a way that the reference to the instance is set before the constructor has finished its execution. This means the method getInstance() returns an object that may not have been initialized completely. To make the code thread-safe, the keyword volatile can be used since Java 5 for the instance variable. Variables that are marked as volatile get only visible to other threads once the constructor of the object has finished its execution completely.
Source
volatile
usage in Java:
The fail-fast iterators are typically implemented using a volatile
counter on the list object.
Iterator
is created, the current value of the counter is embedded in the Iterator
object.Iterator
operation is performed, the method compares the two counter values and throws a ConcurrentModificationException
if they are different.The implementation of fail-safe iterators is typically light-weight. They typically rely on properties of the specific list implementation's data structures. There is no general pattern.
“… the volatile modifier guarantees that any thread that reads a field will see the most recently written value.” - Josh Bloch
If you are thinking about using volatile
, read up on the package java.util.concurrent which deals with atomic behaviour.
The Wikipedia post on a Singleton Pattern shows volatile in use.
Every thread accessing a volatile field will read its current value before continuing, instead of (potentially) using a cached value.
Only member variable can be volatile or transient.
Below is a very simple code to demonstrate the requirement of volatile
for variable which is used to control the Thread execution from other thread (this is one scenario where volatile
is required).
// Code to prove importance of 'volatile' when state of one thread is being mutated from another thread.
// Try running this class with and without 'volatile' for 'state' property of Task class.
public class VolatileTest {
public static void main(String[] a) throws Exception {
Task task = new Task();
new Thread(task).start();
Thread.sleep(500);
long stoppedOn = System.nanoTime();
task.stop(); // -----> do this to stop the thread
System.out.println("Stopping on: " + stoppedOn);
}
}
class Task implements Runnable {
// Try running with and without 'volatile' here
private volatile boolean state = true;
private int i = 0;
public void stop() {
state = false;
}
@Override
public void run() {
while(state) {
i++;
}
System.out.println(i + "> Stopped on: " + System.nanoTime());
}
}
When volatile
is not used: you'll never see 'Stopped on: xxx' message even after 'Stopping on: xxx', and the program continues to run.
Stopping on: 1895303906650500
When volatile
used: you'll see the 'Stopped on: xxx' immediately.
Stopping on: 1895285647980000
324565439> Stopped on: 1895285648087300
Demo: https://repl.it/repls/SilverAgonizingObjectcode
You'll need to use 'volatile' keyword, or 'synchronized' and any other concurrency control tools and techniques you might have at your disposal if you are developing a multithreaded application. Example of such application is desktop apps.
If you are developing an application that would be deployed to application server (Tomcat, JBoss AS, Glassfish, etc) you don't have to handle concurrency control yourself as it already addressed by the application server. In fact, if I remembered correctly the Java EE standard prohibit any concurrency control in servlets and EJBs, since it is part of the 'infrastructure' layer which you supposed to be freed from handling it. You only do concurrency control in such app if you're implementing singleton objects. This even already addressed if you knit your components using frameworkd like Spring.
So, in most cases of Java development where the application is a web application and using IoC framework like Spring or EJB, you wouldn't need to use 'volatile'.
No one has mentioned the treatment of read and write operation for long and double variable type. Reads and writes are atomic operations for reference variables and for most primitive variables, except for long and double variable types, which must use the volatile keyword to be atomic operations. @link