fanghaos

fanghaos

1p

2 comments posted · 4 followers · following 0

6 years ago @ Preshing on Programming - Acquire and Release Se... · 0 replies · +5 points

Thanks for this post!
I am studying the book C++ concurrency in Act, and here is an example I am confused, it's in 5.3.2 ACQUIRE-RELEASE ORDERING Listing 5.7 Acquire-release doesn’t imply a total ordering page 133.
#include <atomic>
#include <thread>
#include <assert.h>

std::atomic<bool> x,y;
std::atomic<int> z;
void write_x()
{
x.store(true,std::memory_order_release);
}
void write_y()
{
y.store(true,std::memory_order_release);
}
void read_x_then_y()
{
while(!x.load(std::memory_order_acquire));
if(y.load(std::memory_order_acquire)) // 1
++z;
}
void read_y_then_x()
{
while(!y.load(std::memory_order_acquire));
if(x.load(std::memory_order_acquire)) //2
++z;
}
int main()
{
x=false;
y=false;
z=0;
std::thread a(write_x);
std::thread b(write_y);
std::thread c(read_x_then_y);
std::thread d(read_y_then_x);
a.join();
b.join();
c.join();
d.join();
assert(z.load()!=0); // 3
}
The author said "In this case the assert 3 can fire (just like in the relaxed-ordering case), because it’s possible for both the load of x 2 and the load of y 1 to read false. x and y are written by different threads, so the ordering from the release to the acquire in each case has no effect on the operations in the other threads.
Figure 5.6 shows the happens-before relationships from listing 5.7, along with a possible outcome where the two reading threads each have a different view of the world. This is possible because there’s no happens-before relationship to force an ordering, as described previously."

In my option, the function "read_x_then_y" and "read_y_then_x" use the memory_order_acquire, the subsequent statements after memory_order_acquire won't be reorder to the location that is before the statement which use memory_order_acquire. So, the statement if(y.load(std::memory_order_acquire)) ++z won't be executed before while(!x.load(std::memory_order_acquire));, if(x.load(std::memory_order_acquire)) ++z won't be executed before while(!y.load(std::memory_order_acquire));.
If I understand you correctly, the z will not be 0.
Do you think so? Thanks a lot

6 years ago @ Preshing on Programming - Memory Reordering Caug... · 1 reply · +5 points

Thanks for this great article firstly.
I have one question:
As the annotation in code, the _ReadWriteBarrier() will prevent compiler reordering only. Why the r1 and r2 will always be set after x = 1 and y=1? Does it exist this conditions:
Time 0: x = 1 in thread 1
Time 1: r1 = y in thread 1, but this time, y is not been set to 1 by thread 2, may be the random in thread 2 took a long time, and the y is not set yet. So, the r1 is 0
Time 2: y = 1 in thread 2
Time 3: r2 = x, in thread 2, r2 is 1.
If this case happen, I think it can't say that cpu reorder instructions.
Is my understanding wrong?