If on one thread I would be writing to a primitive-type variable, such as int
, and the other would be reading it, would there be a possibility of reading partially modified data, as with more complex data types?
If yes, then would my only rescue be either atomic
or mutex
or is there a solution with less performance overhead?
By the wording of the standard yes: accessing the same non-atomic
object from more than one thread, where at least one access is a write, is undefined behavior. So not only could you see "half-written" or "corrupt" primitive data, other things are possible such as corruption of unrelated data, infinite loops, your computer becoming sentient and building a time machine and traveling to the past to convince your ancestors never to pursue the activities that would lead to your birth, segmentation faults, noxious gases being emitted from your USB ports, etc.
In practice, I'm not aware of how this could happen on modern architectures when writing aligned values of primitive types, other than "wide" primitive types that aren't natively supported by the hardware (e.g., some multi-socket AMD machines fail to write aligned 128-bit values atomically). Compilers will generally emit full-width loads and stores, so I don't know of a realistic scenario where you'd be tripped up by e.g. a compiler transforming a 32-bit store into two 16-bit stores, although it is perfectly within its rights to.
That doesn't mean you should do it: the compiler can make other assumptions that can trip you up: e.g., that the value never changes and hence it doesn't need to be re-read at all. More importantly, what you may want is std::atomic
in concert with std::memory_order_relaxed
in key places which often has zero or almost zero performance implications. It's a sharp tool though.