Rather than explaining what volatile does, allow me to explain when you should use volatile.
- When inside a signal handler. Because writing to a
volatilevariable is pretty much the only thing the standard allows you to do from within a signal handler. Since C++11 you can usestd::atomicfor that purpose, but only if the atomic is lock-free. - When dealing with
setjmpaccording to Intel. - When dealing directly with hardware and you want to ensure that the compiler does not optimize your reads or writes away.
For example:
volatile int *foo = some_memory_mapped_device;
while (*foo)
; // wait until *foo turns false
Without the volatile specifier, the compiler is allowed to completely optimize the loop away. The volatile specifier tells the compiler that it may not assume that 2 subsequent reads return the same value.
Note that volatile has nothing to do with threads. The above example does not work if there was a different thread writing to *foo because there is no acquire operation involved.
In all other cases, usage of volatile should be considered non-portable and not pass code review anymore except when dealing with pre-C++11 compilers and compiler extensions (such as msvc’s /volatile:ms switch, which is enabled by default under X86/I64).