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:
volatile bool keepRunning = true;
void Stuff() {
int notAPointer = 0;
notAPointer = (int)(&keepRunning); //Don't do this! Especially on 64-bit processors!
while(keepRunning) {
*(bool*)(notAPointer) = false;
}
printf("The loop terminated!");
}
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)