Способствует ли порядок изменения отношениям "произойдет до"?
// Thread 1
// do A
x.store(1, std::memory_order_release); // operation1
// Thread 2
// do B
x.store(2, std::memory_order_release); // operation2
// Thread 3
x.load(std::memory_order_acquire); // operation3
Я понял, что если поток 3 читает значение, записанное потоком 1, операции освобождения и получения синхронизируются, и эффект A
виден в теме 3
Но что, если дело в том, что:
- порядок модификации для
x
это 1, 2 - thread3 читает значение, записанное thread2, таким образом, 2 происходит до 3.
Есть ли связь между 1 и 3?
или, по сути, вносит ли порядок изменения в отношение " случается до"?
4 ответа
Нет, между операцией 1 и операцией 3 не происходит никаких отношений.
Атомная операция A, которая выполняет операцию освобождения атомарного объекта M, синхронизируется с атомарной операцией B, которая выполняет операцию получения для M и получает свое значение от любого побочного эффекта в последовательности выпуска, возглавляемой A.
... и, к сожалению, Операция 2 не находится в последовательности выпуска, возглавляемой Операцией 1 согласно [intro.races] / 5:
Последовательность освобождения, возглавляемая операцией освобождения атомарного объекта M, представляет собой максимальную непрерывную подпоследовательность побочных эффектов в порядке модификации M, где первая операция - A, а каждая последующая операция - атомарное чтение-изменение-запись операция.
В результате мы не можем построить взаимосвязь между событиями до операции между операцией 1 и другими операциями, поэтому между операцией 1 и операцией 3 не существует связи между событиями.
Если я правильно понимаю ваш вопрос, нет никаких дополнительных гарантий по общему упорядочению в результате того, какой порядок упорядочения памяти вы используете. Нет никакой блокировки, чтобы это произошло.
В вашем примере вы показываете, что поток 1 и поток 2 работают с x одинаково. Следовательно, отношение между потоком 1 и потоком 3 должно быть точно таким же, как отношение между потоком 2 и потоком 3.
В вашем примере не показаны какие-либо строки кода, которые бы ограничивали порядок, в котором фактически выполняются три операции. Другими словами, просто взглянув на эти три утверждения, невозможно сказать, вернется ли операция загрузки 1
, или же 2
или какое-то предыдущее значение x
,
"происходит раньше" означает, что если a произошло раньше, чем b, то эффекты видны b даже в другом потоке.
"случается раньше" не означает, что a
гарантированно произойдет раньше b
, это только означает, что если a
получилось, b
увидим это. это ваша работа как разработчика, чтобы убедиться, a
происходит раньше b
, если это важно для вашего приложения.
"выпуск" означает: любая запись видна другому потоку, который читает значение атомарно. компилятору и процессору не разрешается путать код и делать атомарные операции чтения и записи в одном и том же потоке перед этой операцией выпуска.
"приобретать" означает: любая запись, выполненная с семантикой релиза или более сильной, видна этому потоку, если читать атомарно. компилятору и процессору не разрешается путать код и выполнять атомарные операции чтения и записи в одном и том же потоке после этой операции получения.
обратите внимание, что каждое действие, совершаемое с атомарной переменной, видно по потокам - это первоначальная причина, по которой атомы были созданы. значение x
всегда хранится в нем последнее значение, упорядочение памяти говорит о предотвращении переупорядочения в том же потоке, а не о синхронизации потока кода с другими потоками.
почему некоторые операции чтения и записи могут быть испорчены компилятором и процессором? Оптимизации.