I've seen this sentence:
the general rule is, if you have variables of primitive type that must be shared among multiple threads, declare those variables volatile
from this article, and this sentence:
In general, any data that may be undated asynchronously should be declared to be volatile.
from this page, now considering this introduced rule I'd like to know could you bring an example of a case where despite existence of asynchronous access to a data declaring that data volatile has no use in practice or there's no such exceptional case and the rule is strict.
I would say that in theory those rules are absolutely right, and volatile is needed every time when a variable is accessed by 2 threads. (Even when using mutexes, cause they don't prevent compiler optimizations.) But in practice compilers are good enough at recognizing situations where a variable might be modified outside a particular function so that its value shouldn't be cached in registers. In most cases volatile is not necessary.
I once did some testing in MSVC by inspecting the assembler output for different situations, and all it took to prevent a variable from being cached was to have another function writing to the same variable or taking its address. Global variables were never optimized unless "whole program optimization" was turned on (so the compiler can be sure the variable is not modified in other translation units).
Before you take the article you linked to first too seriously, you might want to read another. In a later posting on Usenet, Andrei later admitted that parts of the original article were just plain wrong, and pointed to this one as giving a more realistic view of things (though note that the link he gives to it there seems to have gone stale).
To follow up on Mike's answer, it's useful in cases like this (global variables used to avoid complexity for this example):
Depending on how complex
thread_body
is, the compiler may elect to cache the value ofthread_running
in a register when the thread begins running, which means it will never notice if the value changes to false.volatile
forces the compiler to emit code that will check the actualthread_running
variable on every loop.Likewise, the C++ standard does not specify how volatile should work, you have to look at what a particular compiler does for a particular platform. Also volatile is a bit subtle and what it does, depends on the compiler and the memory model of the target platform. Locks are way more intuitive to use.
I can't speak for the actual asynchronous access scenario, since I'm not too good at multithreading, but what the
volatile
modifier does is tell the compiler:"Listen, this may change at any time, so don't cache it or put it in a register or do anything crazy like that, okay?"
It does not protect against asynchronous writes, it simply disables optimizations that are invalid if the variable can be changed by external forces.
Edit: As a potential example, one that doesn't involve multithreading (but, does involve exceptionally convoluted code ;), here's a case where volatile is important:
Without that volatile modifier, the compiler might go "Hey, keepRunning is never modified, so I don't even need to generate code that checks it!", when in reality we're simply modifying it in secret.
(In reality, this would probably still work on a non-optimized build. And, it might also still work if the compiler is smart and notices the pointer being taken. But, the principle is the same)
Read this. Volatile has nothing to do with multi-threading.