Happens before
stackoverflow Confusion about happens before relationship in concurrency
Below is an example given in Concurrency in Action , and the author says the assert may fire, but I don't understand why.
#include <atomic>
#include <thread>
#include <assert.h>
std::atomic<bool> x,y;
std::atomic<int> z;
void write_x_then_y()
{
x.store(true,std::memory_order_relaxed);
y.store(true,std::memory_order_relaxed);
}
void read_y_then_x()
{
while(!y.load(std::memory_order_relaxed));
if(x.load(std::memory_order_relaxed))
++z;
}
int main()
{
x=false;
y=false;
z=0;
std::thread a(write_x_then_y);
std::thread b(read_y_then_x);
a.join();
b.join();
assert(z.load()!=0);
}
NOTE:
read_y_then_x()中,while(!y.load(std::memory_order_relaxed));表明它需要等待y,即它依赖y
As far as I know, in each single thread, sequenced before also means happens before. So in thread a the store to x happens before y, which means x should be modified before y and the result x.store should be visible before y is modified.
But in this example the author says that the store between x and y could be reordered, why? Does that violate the rule of sequenced before and happens before?
comments
This might explain things about relaxed ordering en.cppreference.com/w/cpp/atomic/memory_order#Relaxed_ordering – Sami Kuhmonen Jul 29 '18 at 13:54
@SamiKuhmonen sequenced before relationship does not prevent reordering? Then what's the usage of sequenced before? – scottxiao Jul 29 '18 at 14:13
x.store happens-before y.store and y.load happens-before x.load - but x.store doesn't happen-before x.load. Happens-before relationship is not necessarily transitive in the presence of relaxed operations; that's kind of their whole point. – Igor Tandetnik Jul 29 '18 at 14:20
NOTE: 上述happens-before relation是从源程序中抽象出来的
@IgorTandetnik but y.store happens before while(!y.load(std::memory_order_relaxed)) , so x.store hapeens before x.load? – scottxiao Jul 29 '18 at 14:21
NOTE: 并不能保证 :
y.storehappens beforewhile(!y.load(std::memory_order_relaxed))
The conclusion doesn't follow from the premise(前提). Yes, y.store happens-before y.load. No, x.store does not happen-before x.load. You have a sequentially-consistent model of execution in your head - but relaxed operations violate that model; that's why they are called "relaxed", and that's why they are difficult to reason about. – Igor Tandetnik Jul 29 '18 at 14:23
@IgorTandetnik since y.store happens before y.load==true, and happens before relationship is trasitive, why doesn't x.store happens before x.load? – scottxiao Jul 29 '18 at 14:38
Again, happens-before relationship is not in general transitive. In particular, it is not transitive in the presence of relaxed operations. Would it be too much to ask for you to read a comment in full before responding? – Igor Tandetnik Jul 29 '18 at 14:58
The Concurrency in Action says "It’s also a transitive relation: if A inter-thread happens-before B and B inter-thread happens-before C, then A inter-thread happens-before C.". – scottxiao Jul 29 '18 at 15:02
happens-before and inter-thread happens-before are two different relations. Here, y.load does not inter-thread happens-before x.load (since both are on the same thread). – Igor Tandetnik Jul 29 '18 at 15:14
@IgorTandetnik What's the differences between happens before and inter-thread happens before? – scottxiao Jul 29 '18 at 15:41
eel.is/c++draft/intro.multithread#intro.races-10 – Igor Tandetnik Jul 29 '18 at 15:45
@IgorTandetnik Your linkage says they are not different relations, inter-thread happens before belongs to happens before. – scottxiao Jul 29 '18 at 16:14
They are different relations, where one is a subset of the other. The subset is transitive; the superset is not. In particular, if A inter-thread happens-before B and B is sequenced-before C, this doesn't necessarily mean that A happens-before C (even though A happens-before B and B happens-before C). – Igor Tandetnik Jul 29 '18 at 16:23
A
From thread a perspective, it looks as if x.store happens before y.store. However, from thread b perspective, it can look as if they are reordered. https://koheiotsuka701.medium.com/memory-model-basic-d8b5f8fddd5f