Это плохой пример, хотя он иллюстрирует, насколько может быть изнурительной расслабленной атомикой, я полагаю.
[intro.execution] p9:
Вычисление каждого значенияи побочный эффект, связанный с полным выражением, секвенируется перед каждым вычислением значения, и побочный эффект, связанный со следующим полным выражением, которое будет оцениваться.
[atomics.order] p2:
Атомная операция A , которая выполняет операцию освобождения для атомарного объекта M , синхронизируется с атомарной операцией B , которая выполняет операцию получения для M и берет свое значение от любого побочного эффекта в последовательности выпуска, озаглавленной A .
В результате показанные оценки объединяются в последовательность переди синхронизированы с отношениями:
Thread 1 Thread 2 Thread 3
y.store(20)
|
| s.b.
V s.w.
x.store(10) --------> x.load() == 10
|
| s.b.
V s.w.
y.store(10) --------> y.load() == 10
|
| s.b.
V
x.load() == ?
И поэтому каждая оценка в цепочке происходит до следующего (см. [intro.races] p9-10).
[intro.races] стр. 15,
Если вычисление значения A атомарного объекта M происходит до вычисления значения B из M и A берет свое значение из побочного эффекта X при M , тогда значение, вычисленное как B , должно быть либо значением, сохраненным в X или значение, сохраненное побочным эффектом Y на M , где Y следует X в порядке изменения M .
Здесь A - нагрузка в потоке 2, принявшая значение 10, B - нагрузка в потоке 3 (вутверждать).Поскольку A происходит раньше, чем B , и никаких других побочных эффектов для x
, B также должно быть 10.
У Херба Саттера гораздо более простой пример в его блоге :
T1: x = 1;
T2: y = 1;
T3: if( x == 1 && y == 0 ) puts("x first");
T4: if( y == 1 && x == 0 ) puts("y first");
Вам абсолютно необходима последовательная последовательность, чтобы гарантировать, что напечатана не более одной строки.