Barriers and synchronization points with non-atomic variables - data race?
Asked Answered
F

1

6

Consider the following program:

int                        i{0};
std::experimental::barrier b{2};

int main()
{
    std::thread t0{[] {
        b.arrive_and_wait();
        std::cout << i << '\n';
    }};

    std::thread t1{[] {
        i = 2;
        b.arrive_and_wait();
    }};

    t0.join();
    t1.join();
}

Is this program guaranteed to print out 2, even though i is not an atomic variable?

According to cppreference:

Calls to arrive_and_wait synchronizes with the start of the completion phase of the barrier. The completion of the completion phase synchronizes with the return from the call.

Calls to arrive_and_drop and arrive_and_wait never introduce data races with themselves or each other.

This suggests that there is a synchronization point on each arrive_and_wait call. However I am not sure if the compiler is allowed to reorder the read/write operations on i, since it is non-atomic.

Fabrice answered 20/11, 2018 at 11:6 Comment(1)
Bartop is right.. "Calls to arrive_and_wait() synchronize with the return from the call". Therein lies your answer.. If A synchronizes with B, statements sequenced before A (i = 2) inter-thead happen before statements that are sequenced after B (cout << i). Whether or not those statements are atomic is not relevant; It is the exact same mechanism that a mutex uses to synchronize non-atomic data between threads.Mazza
M
3

From what I understand from std::barrier reference(my emphasis) :

A barrier has a completion phase, which is executed by one of the participating threads once all threads in the set of participating threads arrive at the synchronization point. The arrive_and_wait and arrive_and_drop calls synchronize with the start of the completion phase; the end of the completion phase synchronizes with the returns from all calls blocked by its completion.

you can assume that all changes made before barrier in different threads are visible in other threads, even if they are not not atomic. As this reference points out (my emphasis):

Between threads, evaluation A inter-thread happens before evaluation B if any of the following is true

1) A synchronizes-with B

2) A is dependency-ordered before B

3) A synchronizes-with some evaluation X, and X is sequenced-before B

4) A is sequenced-before some evaluation X, and X inter-thread happens-before B

5) A inter-thread happens-before some evaluation X, and X inter-thread happens-before B

Messier answered 20/11, 2018 at 11:31 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.