Search code examples
c++multithreadingc++17race-conditiondata-corruption

C++: Can thread race conditions corrupt static/global integer values on a per-byte level?


Let's say I have two threads that randomly increment or decrement from a static int variable in the global scope. My program is not concerned with the exact value of this variable, only whether it is generally increasing or decreasing over-time.

Though I have written some assembly code during college, I am not familiar with how CPUs deal with multithreading and communicate between cores. Is there any chance that two simultaneous writes can corrupt a global variable on a per-byte level? Or are reads and writes to memory (e.g. move, load, store) always atomic?

I use Visual Studio 2022 and C++17, and am hoping to target all modern desktop CPUs (intel, AMD).


Solution

  • The CPU is the least of your problems here. C++ states that any of these interactions represents undefined behavior. As such, consider the following code:

    int i; //Global variable.
    
    void some_func()
    {
      i = 5;
    
      if(i > 5)
      {
        //A
      }
    }
    

    The compiler can see all of the code between assigning to i and checking its value. It can see that there is no inter-thread synchronization between these two operations. Because the C++ standard states that any modifications to i from another thread under these circumstances yield undefined behavior, the compiler is free to assume that such modifications do not happen.

    Therefore, the compiler knows that i will never be greater than 5 at this point and therefore may remove the block "A" and conditional test, not even emitting assembly that could be executed.

    That is what "undefined behavior" means.

    If you want to play around with things like that, if you want to actually use the behavior of your CPU/cache/etc in such scenarios, you're going to need to operate in a lower-level language. And for what it's worth, the C standard has more-or-less the same wording, so C ain't it.

    So long as you are working in C or C++, the question you are asking is fundamentally unanswerable.