Why do we use volatile keyword?
Consider this code,
int some_int = 100;
while(some_int == 100)
{
//your code
}
When this program gets compiled, the compiler may optimize this code, if it finds that the program never ever makes any attempt to change the value of some_int
, so it may be tempted to optimize the while
loop by changing it from while(some_int == 100)
to something which is equivalent to while(true)
so that the execution could be fast (since the condition in while
loop appears to be true
always). (if the compiler doesn't optimize it, then it has to fetch the value of some_int
and compare it with 100, in each iteration which obviously is a little bit slow.)
However, sometimes, optimization (of some parts of your program) may be undesirable, because it may be that someone else is changing the value of some_int
from outside the program which compiler is not aware of, since it can't see it; but it's how you've designed it. In that case, compiler's optimization would not produce the desired result!
So, to ensure the desired result, you need to somehow stop the compiler from optimizing the while
loop. That is where the volatile
keyword plays its role. All you need to do is this,
volatile int some_int = 100; //note the 'volatile' qualifier now!
In other words, I would explain this as follows:
volatile
tells the compiler that,
"Hey compiler, I'm volatile and, you
know, I can be changed by some XYZ
that you're not even aware of. That
XYZ could be anything. Maybe some
alien outside this planet called
program. Maybe some lightning, some
form of interrupt, volcanoes, etc can
mutate me. Maybe. You never know who
is going to change me! So O you
ignorant, stop playing an all-knowing
god, and don't dare touch the code
where I'm present. Okay?"
Well, that is how volatile
prevents the compiler from optimizing code. Now search the web to see some sample examples.
Quoting from the C++ Standard ($7.1.5.1/8)
[..] volatile is a hint to the
implementation to avoid aggressive
optimization involving the object
because the value of the object might
be changed by means undetectable by an
implementation.[...]
Related topic:
Does making a struct volatile make all its members volatile?
What is the volatile keyword useful for?
volatile
has semantics for memory visibility. Basically, the value of a volatile
field becomes visible to all readers (other threads in particular) after a write operation completes on it. Without volatile
, readers could see some non-updated value.
To answer your question: Yes, I use a volatile
variable to control whether some code continues a loop. The loop tests the volatile
value and continues if it is true
. The condition can be set to false
by calling a "stop" method. The loop sees false
and terminates when it tests the value after the stop method completes execution.
The book "Java Concurrency in Practice," which I highly recommend, gives a good explanation of volatile
. This book is written by the same person who wrote the IBM article that is referenced in the question (in fact, he cites his book at the bottom of that article). My use of volatile
is what his article calls the "pattern 1 status flag."
If you want to learn more about how volatile
works under the hood, read up on the Java memory model. If you want to go beyond that level, check out a good computer architecture book like Hennessy & Patterson and read about cache coherence and cache consistency.
Why does volatile exist?
volatile
is needed if you are reading from a spot in memory that, say, a completely separate process/device/whatever may write to.
I used to work with dual-port ram in a multiprocessor system in straight C. We used a hardware managed 16 bit value as a semaphore to know when the other guy was done. Essentially we did this:
void waitForSemaphore()
{
volatile uint16_t* semPtr = WELL_KNOWN_SEM_ADDR;/*well known address to my semaphore*/
while ((*semPtr) != IS_OK_FOR_ME_TO_PROCEED);
}
Without volatile
, the optimizer sees the loop as useless (The guy never sets the value! He's nuts, get rid of that code!) and my code would proceed without having acquired the semaphore, causing problems later on.
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.
Purpose/advantages of volatile
When a multithreaded program is running, and there is some shared variable which isn't declared as volatile
, what these threads do is create a local copy of the variable, and work on the local copy instead. So the changes on the variable aren't reflected. This local copy is created because cached memory access is much faster compared to accessing variables from main memory.
When you declare a variable as volatile
, it tells the program NOT to create any local copy of the variable and use the variable directly from the main memory.
By declaring a variable as volatile
, we are telling the system that its value can change unexpectedly from anywhere, so always use the value which is kept in the main memory and always make changes to the value of the variable in the main memory and not create any local copies of the variable.
Note that volatile is not a substitute for synchronization, and when a field is declared volatile, the compiler and runtime are put on notice that this variable is shared and that operations on it should not be reordered with other memory operations. Volatile variables are not cached in registers or in caches where they are hidden from other processors, so a read of a volatile variable always returns the most recent write by any thread.
Why is volatile not considered useful in multithreaded C or C++ programming?
The problem with volatile
in a multithreaded context is that it doesn't provide all the guarantees we need. It does have a few properties we need, but not all of them, so we can't rely on volatile
alone.
However, the primitives we'd have to use for the remaining properties also provide the ones that volatile
does, so it is effectively unnecessary.
For thread-safe accesses to shared data, we need a guarantee that:
- the read/write actually happens (that the compiler won't just store the value in a register instead and defer updating main memory until much later)
- that no reordering takes place. Assume that we use a
volatile
variable as a flag to indicate whether or not some data is ready to be read. In our code, we simply set the flag after preparing the data, so all looks fine. But what if the instructions are reordered so the flag is set first?
volatile
does guarantee the first point. It also guarantees that no reordering occurs between different volatile reads/writes. All volatile
memory accesses will occur in the order in which they're specified. That is all we need for what volatile
is intended for: manipulating I/O registers or memory-mapped hardware, but it doesn't help us in multithreaded code where the volatile
object is often only used to synchronize access to non-volatile data. Those accesses can still be reordered relative to the volatile
ones.
The solution to preventing reordering is to use a memory barrier, which indicates both to the compiler and the CPU that no memory access may be reordered across this point. Placing such barriers around our volatile variable access ensures that even non-volatile accesses won't be reordered across the volatile one, allowing us to write thread-safe code.
However, memory barriers also ensure that all pending reads/writes are executed when the barrier is reached, so it effectively gives us everything we need by itself, making volatile
unnecessary. We can just remove the volatile
qualifier entirely.
Since C++11, atomic variables (std::atomic<T>
) give us all of the relevant guarantees.
What is the significance of the volatile key word with respect to Embedded Systems?
In the embedded systems world, one of the key aspects of the volatile
key-word is that it denotes a variable that may change at any time (eg an external/hardware data input - eg an ADC) and therefore the compiler must not optimise use.
But specifically, when used with a control register, it indicates that a read access may in fact change the data!
As a general rule of thumb, I would recommend the use of the volatile
qualifier in all of the following:
- All hardware register accesses(read and write)
- All variables that are accessible in multiple threads (especially interrupt handlers)
Note: accessing a volatile
is not necessarily atomic, so it is imperative that you know your hardware and your code structure.
Related Topics
Lock-Free Progress Guarantees in a Circular Buffer Queue
Copying a Polymorphic Object in C++
Py_Initialize Fails - Unable to Load the File System Codec
Deprecated Header ≪Codecvt≫ Replacement
When Were the 'And' and 'Or' Alternative Tokens Introduced in C++
How to Open an Std::Fstream (Ofstream or Ifstream) With a Unicode Filename
Using Stdlib'S Rand() from Multiple Threads
How to Link C++ Program With Boost Using Cmake
Writing Bmp Image in Pure C/C++ Without Other Libraries
Why Are Function Pointers and Data Pointers Incompatible in C/C++
Library Function For Permutation and Combination in C++
How to Link Opencv in Qtcreator and Use Qt Library
Removing Item from Vector, While in C++11 Range 'For' Loop
How to Increase the Re-Usability of This Key-Oriented Access-Protection Pattern