Search code examples
cmultithreadingc++11java-memory-modelmemory-model

Does this example contain a data race?


Here is the originan question, but mine have some differences with it. C++ memory model - does this example contain a data race?

My question:

//CODE-1: initially, x == 0 and y == 0
if (x) y++; // pthread 1
if (y) x++; // pthread 2

Note: the code above is written in C, not C++ (without a memory model). So does it contain a data race?

From my point of view: if we view the code in Sequential Consistency memory model, there is no data race because x and y will never be both non-zero at the same time. However, we can never assume a Sequential Consistency memory model, so the compilier reordering could make a transformation that respect to the intra-thread correctness because the compiler isn't aware of the existence of thread.......right?

So the code could be transformed to:

//CODE-2
y++; if (!x) y--;
x++; if (!y) x--;

the transformation above doesn't violate the sequential correctness so it's correct.It's not the fault of the compilier, right? So I agree with the view that the CODE-1 contains a data race.What about you?

I have an extra question, C++11 with a memory model can solve this data race because the compilers are aware of the thread, so they will do their reorder according to the memory model type, right?


Solution

  • The C++ standard defines a data race (which triggers undefined behavior) as:

    § 1.10.1-2 [intro.races]
    Two expression evaluations conflict if one of them modifies a memory location (..) and the other one reads or modifies the same memory location.

    Per the C++ memory model rules, your first code fragment contains no data race because the C++ standard forbids compiler transformations that would introduce such a race:

    § 1.10.1-21 [intro.races]
    Compiler transformations that introduce assignments to a potentially shared memory location that would not be modified by the abstract machine are generally precluded by this International Standard, since such an assignment might overwrite another assignment by a different thread in cases in which an abstract machine execution would not have encountered a data race.

    So it says that if the condition in the if-statement (x) yields false, no transformation is allowed that would modify y, even if the end result is that y appears unmodified.

    The second example clearly contains a data race because 2 threads can write and read x at the same time (same applies to y).

    Note that both C++ and C have a memory model since version 11. If you use a compiler that does not support C11, multithreaded behavior is not officially defined.

    Here is a question that shows an example of an illegal compiler transformation.