Rather than explaining what volatile
does, allow me to explain when you should use volatile
.
- When inside a signal handler. Because writing to a
volatile
variable is pretty much the only thing the standard allows you to do from within a signal handler. Since C++11 you can use std::atomic
for that purpose, but only if the atomic is lock-free.
- When dealing with
setjmp
according 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).
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…