Multithreaded programming is notoriously hard, especially when optimizations are carried out by the compiler, runtime, or the processor hardware. In particular, reads and writes to memory can sometimes be reordered to improve execution efficiency.
Luckily, you almost never have to worry about those subtleties if you’re using synchronization primitives such as the
lock keyword to coordinate multithreaded access to state. You can find more information about such primitives in Chapter 30, “Task Parallelism and Data Parallelism.” Nonetheless, let’s consider a few things about the behavior of volatile fields, just in case you encounter code that uses this language feature. Also, in case you ever need to write lock-free code, understanding ...