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
andarrive_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.
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With