简体   繁体   中英

C++ Is writing and reading a variable from different threads undefined behavior

Since I've started multi-threading, I've been asking myself this one question :

Is writing and reading a variable from different threads undefined behavior?

Let's use the minimal example where we increment an integer in a thread and read the integer inside another one.

void thread1()
{
    x++;
}

void thread2()
{
    if (x == 5)
    {
        //doSomething
    }
}

I understand that the addition operation is not atomic and therefore I could make a read from the second thread while the first thread is in the middle of the adding operation, but there is something i'm not quite sure of.

Does x keeps his value until the whole addition operation is completed and then is assigned this new value, or does x have an intermediate state where reading from it would result in undefined behavior.

If the first theory applies, then reading from x while it's being writing to would simply return the value before the addition and wouldn't be so problematic.

If the second theory is true, could someone explain more in detail what is the process of the addition operation and why it would be undefined behavior (maybe with an example?)

Thanks

The comments already got the basics right.

The compiler, when compiling a single function may consider the ways in which a variable is changed. If the function cannot directly or indirectly change a certain variable, then the compiler may assume that there is no change to that variable whatsoever, unless there's thread synchronization. In that case the compiler must deal with the possibility of another thread changing those variables.

If the compiler assumption is violated (ie you have a bug), then literally anything may happen. This is not constrained, because that would severely restrict optimizers. You may make some assumptions that x has some unique address in memory, but optimizers are known to move variables around and have multiple variables share a single address (just at different times). Such optimizations may very well be justified based on a single-thread assumption, one that your example is violating. Your second thread may think it's looking at x , but it might also be getting y .

x (32bit variable) will be always defined on 32+bits cpu however not so precisely. You know that x can be any value from start up to end range defined by ++.

like in following case: x is initialized to 0 and you call 5 times thread1 the thread 2 can see this x in range from 0 to 5.

It means I can consider assignment of integer to memory as atomic.

There are some reasons why x on both thread is not synchronized eg while x on thread1 is 5 on the thread2 can be 0 in the same time. One of the reason is cpu cache which is different for each core. To synchronise the value between caches you have to use memory barriers. You can use for example std::atomic which do a great job for you

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM