As I understand, for the sequentially consistent and acquire-release memory models if some x.store(some_value)
operation from one thread is synchronized with a x.load()
operation from the another one, then:
Rule 1. All memory operations that happen before the x.store(some_value)
operation must appear before the x.load()
operation.
This point seems clear to me:
-Thread 1-
y = 1;
x.store(2, memory_order_release);
-Thread 2-
if (x.load(memory_order_acquire) == 2)
assert(y == 1)
Here if the compiler places y = 1
operation after x.store(2)
, assert
can fail and this is not the behavior that we expect.
Rule 2. All memory operations that happen after the x.load()
operation must also appear after the x.store(some_value)
operation.
But now I'm confused: why can't the compiler move the statements across load()
operations? How can it violate the expected behavior of the program? I think of a such example:
-Thread 1-
x.store(2, memory_order_release); // x == 0 initially
-Thread 2-
while (x.load(memory_order_acquire) == 1);
y = 2; // y == 0 initially
Here, if compiler places y = 2
operation before while()
, y
becomes 2
(otherwise there is the infinite loop and y
stays unchanged), but this example seems forced (I'm even not sure that compiler can do such "optimization"), and I suspect that there are more realistic situations for which Rule 2 was created.
Could you please give me the explanation of the Rule 2's necessity?
Aucun commentaire:
Enregistrer un commentaire