(Meta: As already pointed out by @comex, this post is from 2010 and it would be helpful with a tag in the title to make that clearer.)
That said, it's an awesome post (not surprising considering the source). I found the initial set-up explaining the concept of C's abstract machine very succinct and nice, it's something I would wish more people discussing the language to be (well) aware of.
I can add a bit of historical context here. John wrote that during the development of WINAVR, the first GCC compiler for AVR. The discussions can be found in the AVR-GCC mailing list archives.
When the 'Small' optimization is used in AVR GCC it is aggressive and leads often to broken code if 'volatile' is not properly used.
AVR GCC, using Small optimization, would remove any variable that has no side effects from the compiler's view. Setting a value in an interrupt handler would be outside of the view of the compiler's abstract machine, so 'flag' variables were often removed. Changes in hardware registers fall into the same category.
These removals result in broken code.
Volatile is never a replacement for atomics or proper locks/mutexes/semaphores.
If hardware such as an interrupt handler or hardware register is not involved, then using volatile is a creating a race condition, which may or may not ever become apparent.
Erich Styger wrote more recently about volatile here.
That said, it's an awesome post (not surprising considering the source). I found the initial set-up explaining the concept of C's abstract machine very succinct and nice, it's something I would wish more people discussing the language to be (well) aware of.
Great post, thanks!