Thread 1 Memory Thread 2
--------- ------- ---------
| | |
| write(data, 100) | |
| -----------------------> | |
| | |
| ====Memory Barrier====== | |
| store(ready, true) | |
| -----------------------> | |
| ====Memory Barrier====== | |
| | |
| | ===Memory Barrier======= |
| | load(ready) == true |
| | <---------------------- |
| | ====Memory Barrier===== |
| | |
| | read(data) |
| | <---------------------- |
| | |
I.e. barriers prevent reordering of operations within a thread, not across threads. It also makes immediately obvious why the seq_cst ordering of both the thread 1 atomic store and the thread 2 atomic load can be relaxed: The last barrier in Thread 1 does not prevent any reordering in this example, hence it can be omitted, leaving only the barrier before the store making it a release operation. Similarly, we can omit the barrier before the first load in thread 2, leaving only the barrier after, making it an acquire operation.[1] well, it is showing the effect of sequential consistency as opposed to acquire-release, so a logical barrier spanning threads is not necessarily wrong, but then you would still need to show a barrier before the last store and the first load.