When exactly do you use the volatile keyword in Java?
You basically use it when you want to let a member variable be accessed by multiple threads but do not need compound atomicity (not sure if this is the right terminology).
class BadExample {
private volatile int counter;
public void hit(){
/* This operation is in fact two operations:
* 1) int tmp = this.counter;
* 2) this.counter = tmp + 1;
* and is thus broken (counter becomes fewer
* than the accurate amount).
*/
counter++;
}
}
the above is a bad example, because you need compound atomicity.
class BadExampleFixed {
private int counter;
public synchronized void hit(){
/*
* Only one thread performs action (1), (2) at a time
* "atomically", in the sense that other threads can not
* observe the intermediate state between (1) and (2).
* Therefore, the counter will be accurate.
*/
counter++;
}
}
Now to a valid example:
class GoodExample {
private static volatile int temperature;
//Called by some other thread than main
public static void todaysTemperature(int temp){
// This operation is a single operation, so you
// do not need compound atomicity
temperature = temp;
}
public static void main(String[] args) throws Exception{
while(true){
Thread.sleep(2000);
System.out.println("Today's temperature is "+temperature);
}
}
}
Now, why can't you just use private static int temperature
? In fact you can (in the sense that that your program won't blow up or something), but the change to temperature
by the other thread may or may not be "visible" to the main thread.
Basically this means that it is even possible that your app. keeps writing Today's temperature is 0
forever if you don't use volatile
(in practice, the value tends to become eventually visible. However, you should not risk not using volatile when necessary, since it can lead to nasty bugs (caused by in-completely constructed objects etc.).
If you put volatile
keyword on something that doesn't need volatile
, it won't affect your code's correctness (i.e. the behaviour will not change). In terms of performance, it will depend on the JVM implementation. In theory you might get a tiny performance degradation because the compiler can't do reordering optimisations, have to invalidate CPU cache etc., but then again the compiler could prove that your field cannot ever be accessed by multiple threads and remove the effect of volatile
keyword completely and compile it to identical instructions.
EDIT:
Response to this comment:
Ok, but why can't we make todaysTemperature synchronized and create a synchronized getter for temperature?
You can and it will behave correctly. Anything that you can with volatile
can be done with synchronized
, but not vice versa. There are two reasons you might prefer volatile
if you can:
- Less bug prone: This depends on the context, but in many cases using
volatile
is less prone to concurrency bugs, like blocking while holding the lock, deadlocks etc. - More performant: In most JVM implementations,
volatile
can have significantly higher throughput and better latency. However in most applications the difference is too small to matter.
Volatile is most useful in lock-free algorithms. You mark the variable holding shared data as volatile when you are not using locking to access that variable and you want changes made by one thread to be visible in another, or you want to create a "happens-after" relation to ensure that computation is not re-ordered, again, to ensure changes become visible at the appropriate time.
The JMM Cookbook describes which operations can be re-ordered and which cannot.
volatile
keyword guarantees that value of the volatile variable will always be read from main memory and not from Thread's local cache.
From java concurrency tutorial :
Using volatile variables reduces the risk of memory consistency errors, because any write to a volatile variable establishes a happens-before relationship with subsequent reads of that same variable
This means that changes to a volatile variable are always visible to other threads. It also means 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.
Regarding your query:
How do I know when I should mark a variable volatile? What are the rules of thumb when figuring out what variables should be volatile in multithreaded code?
If you feel that all reader threads always get latest value of a variable, you have to mark variable as volatile
If you have one writer thread to modify the value of variable and multiple reader threads to read the value of variable, volatile modifier guarantees memory consistency.
If you have multiple threads to write and read variables, volatile
modifier alone does not guaranty memory consistency. You have to synchronize
the code or use high level concurrency constructs like Locks
, Concurrent Collections
, Atomic variables
etc.
Related SE questions/articles:
Volatile variable explanation in Java docs
Difference between volatile and synchronized in Java
javarevisited article
The volatile
can also be used to safely publish immutable objects in a multi-threaded Environment.
Declaring a field like public volatile ImmutableObject foo
secures that all threads always see the currently available instance reference.
See Java Concurrency in Practice for more on that topic.