Two Readers Disagree

Four threads, each running once. a and b are independent atomics that start at 0.

std::atomic<int> a{0}, b{0};

void w1() { a.store(1, std::memory_order_release); }
void w2() { b.store(1, std::memory_order_release); }

void r1() { x1 = a.load(std::memory_order_acquire);
            y1 = b.load(std::memory_order_acquire); }

void r2() { x2 = b.load(std::memory_order_acquire);
            y2 = a.load(std::memory_order_acquire); }

A run reports:

register thread reads value
x1 r1 a 1
y1 r1 b 0
x2 r2 b 1
y2 r2 a 0

Reader 1 saw a change and b not yet, so it concludes the store to a happened first. Reader 2 concludes the opposite. Is this outcome permitted?

A

Yes, and seq_cst would not help either, because two unrelated variables can never be placed in a common order.

B

Yes. Acquire and release order operations only along the individual edges they create, so two independent stores need not appear in one order that both readers agree on. Making all six operations, both stores and all four loads, seq_cst forbids it.

C

No. A release store becomes globally visible at the moment it retires, so the two readers must agree on which store landed first.

D

No. Both readers used acquire loads, and acquire loads are sequentially consistent with each other.