What operations are called non-atomic?
If possible with an example.

    3 answers 3

    Roughly - which may be interrupted by another thread.

    Examples? Well, for example

    if (a) { f(a); } 

    While you considered a , which is equal to true , and were going to execute f(a) , another thread has already made a equal to false :)

    Or even such exotic - in one thread you assign the value of a two-word variable. The first word was recorded, the interruption, another thread reads something half-written from memory. Works, writes something of their own. Here again, control returns to the first thread, and it appends the second half of our variable ...

    • Quick and clear, all in your style) Thank you. - HiHello

    In C ++, atomic operations are only operations on std::atomic , all other operations are non-atomic.

    Under certain conditions, on a certain architecture, operations on “simple” objects can also be atomic, but the C ++ standard is not guaranteed. For example, you have the following code:

     int64_t var{}; var = -1; 

    If we run it on a 64-bit architecture (amd64, for example), then surely the operation var = -1 will be atomic, since the bus allows you to write all 64 bits at a time we will have one mov in assembler. If we compile this code for a 32-bit processor (x86, for example), then this operation will cease to be atomic and will most likely consist of two consecutive mov , since For a single indivisible operation, you can not shove 64 bits of data into a 32-bit bus.

    True, the processors have enough money to turn several operations into one atomic, but these tools will be used with std::atomic . If the processor means for implementing std::atomic not enough, then they go to a higher level - locking mutexes and so on. From the point of view of the processor, such operations cannot be considered atomic, but from the point of view of the application they will be atomic, since at no point in time can the program read a partially recorded value.

    • At least the critical data should be marked as volatile, otherwise the value at the time of switching processes may be in the general-purpose register. Volatile - tells the compiler optimizer that the variable can only be stored in its memory, and not cached by the register. - Pavel Gridin
    • one
      @PavelGridin, volatile , in modern C ++ code, should be used for ports in embedded. I don't see any other use for it at all; critical data that is subject to competition should either be under a mutex or themselves should be std::atomic - again volatile not needed. - ixSci
    • @ixSci, and why on x86_64 you say that var = -1 "will surely be atomic" i.e. not exactly? - xperious
    • @xperious, I do not know why such a construction may not be atomic on the above architecture, but I do not know everything. Those. no one forbids the compiler to remake this call into anything that the standard does not forbid. I just made a similar reservation just in case. - ixSci

    In general, what is atomic and what is not should be looked for in the compiler description, for a specific processor, for example, for some DSPs the assignment is atomic, but usually it is not even atomic, for reliability it is better to use something like std :: atomic