Quote:Original post by frob
This is exactly what I tried to explain above. Just because a single read or write cpu instruction is atomic doesn't mean the entire block of source code is atomic.
If volatile is respected by compiler, then it will organize the code in such a way as to prevent this type of failure.
But!
volatile is not a concurrency primitive. It's merely support for developing those. Up until the increased popularity of multi-core chipsets, as well as
Quote:Anything less than this kind of true IPC is not reliable, and will be a source of nightmarish bugs later on.
volatile is there to keep compiler from being too smart:
bool running = true;while (running) {}
In this example, compiler is perfectly free to not even allocate
running. It's never changed, and all we have is an infinite loop.
Marking
running volatile will tell compiler that this variable will be modified by multiple threads, and it should be pessimistic about optimization.
So in order to do stay away from obscure and inexplainable bugs (as the above example), cautious and appropriate use of volatile is perfectly warranted.
In general, best concurrency is obtained by replicating the state, avoiding any kind of locks altogether. But there are several edge cases (lock-less algorithms, various shared data where consistency isn't important), where volatile is either required, or useful. But they really are edge cases.
I digress though, someone should run the following test:
- A thread is reading a timer (1000Hz), storing last result into int sized variable
- Multiple consumers read this shared variable (1..50kHz, variable or fixed rates)
1) shared variable is marked volatile
2) shared variable is accessed through some synchronization primitive
3) shared variable is plain old int
Choice 3 is probably worst, since compiler might optimize the access away. As for 1 and 2, I have no immediate rule of thumb which would be faster/more light-weight. On one hand, under 1) access would be unoptimized (whatever that means in the context), whereas under 2) it would require use of mutex, which is generally considered heavy-weight, especially for this type of fine-grained access.