Does the C++ volatile keyword introduce a memory fence?

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).


Does the C++ volatile keyword introduce a memory fence?

A C++ compiler which conforms to the specification is not required to introduce a memory fence. Your particular compiler might; direct your question to the authors of your compiler.

The function of "volatile" in C++ has nothing to do with threading. Remember, the purpose of "volatile" is to disable compiler optimizations so that reading from a register that is changing due to exogenous conditions is not optimized away. Is a memory address that is being written to by a different thread on a different CPU a register that is changing due to exogenous conditions? No. Again, if some compiler authors have chosen to treat memory addresses being written to by different threads on different CPUs as though they were registers changing due to exogenous conditions, that's their business; they are not required to do so. Nor are they required -- even if it does introduce a memory fence -- to, for instance, ensure that every thread sees a consistent ordering of volatile reads and writes.

In fact, volatile is pretty much useless for threading in C/C++. Best practice is to avoid it.

Moreover: memory fences are an implementation detail of particular processor architectures. In C#, where volatile explicitly is designed for multithreading, the specification does not say that half fences will be introduced, because the program might be running on an architecture that doesn't have fences in the first place. Rather, again, the specification makes certain (extremely weak) guarantees about what optimizations will be eschewed by the compiler, runtime and CPU to put certain (extremely weak) constraints on how some side effects will be ordered. In practice these optimizations are eliminated by use of half fences, but that's an implementation detail subject to change in the future.

The fact that you care about the semantics of volatile in any language as they pertain to multithreading indicates that you're thinking about sharing memory across threads. Consider simply not doing that. It makes your program far harder to understand and far more likely to contain subtle, impossible-to-reproduce bugs.


What David is overlooking is the fact that the C++ standard specifies the behavior of several threads interacting only in specific situations and everything else results in undefined behavior. A race condition involving at least one write is undefined if you don't use atomic variables.

Consequently, the compiler is perfectly in its right to forego any synchronization instructions since your CPU will only notice the difference in a program that exhibits undefined behavior due to missing synchronization.


First of all, the C++ standards do not guarantee the memory barriers needed for properly ordering the read / writes that are non atomic. volatile variables are recommended for using with MMIO, signal handling, etc. On most implementations volatile is not useful for multi-threading and it's not generally recommended.

Regarding the implementation of volatile accesses, this is the compiler choice.

This article, describing gcc behavior shows that you cannot use a volatile object as a memory barrier to order a sequence of writes to volatile memory.

Regarding icc behavior I found this source telling also that volatile does not guarantee ordering memory accesses.

Microsoft VS2013 compiler has a different behavior. This documentation explains how volatile enforces Release / Acquire semantics and enables volatile objects to be used in locks / releases on multi-threaded applications.

Another aspect that needs to be taken into considerations is that the same compiler may have a different behavior wrt. to volatile depending on the targeted hardware architecture. This post regarding the MSVS 2013 compiler clearly states the specifics of compiling with volatile for ARM platforms.

So my answer to:

Does the C++ volatile keyword introduce a memory fence?

would be: Not guaranteed, probably not but some compilers might do it. You should not rely on the fact that it does.