Автономная граница налагает более строгий порядок, чем атомарная операция с тем же ограничением порядка, но это не меняет направления, в котором применяется порядок.
Bot, операция атомарного выпуска и автономное ограждение выпуска являются однонаправленными, но атомарная операция приказывает по отношению к себе, тогда как атомарное ограждение устанавливает порядок по отношению к другим хранилищам.
Например, атомарная операция с семантикой выпуска:
std::atomic<int> sync{0};
// memory operations A
sync.store(1, std::memory_order_release);
// store B
Это гарантирует, что никакая часть операции с памятью A (загрузка и сохранение) не может быть (явно) переупорядочена с помощью самого атомарного хранилища. Но это однонаправлено, и правила упорядочения не применяются к операциям с памятью, которые выполняются после атомарной операции; следовательно, хранилище B все еще можно переупорядочить с помощью любой из операций с памятью в A.
Ограничение автономного выпуска изменяет это поведение:
// memory operations A
std::atomic_thread_fence(std::memory_order_release);
// load X
sync.store(1, std::memory_order_relaxed);
// stores B
Это гарантирует, что никакая операция с памятью в A не может быть (явно) переупорядочена с помощью любых хранилищ, которые упорядочены после ограничения выпуска. Здесь хранилище в B больше не может быть переупорядочено с помощью каких-либо операций с памятью в A, и поэтому ограничение выпуска сильнее, чем операция атомарного выпуска. Но он также является однонаправленным, поскольку загрузка из X все еще может быть переупорядочена с помощью любой операции с памятью в A.
Разница невелика, и обычно операция атомарного выпуска предпочтительнее изолированного выпуска.
Правила для отдельного ограждения для приобретения аналогичны, за исключением того, что он обеспечивает выполнение заказа в противоположном направлении и работает с нагрузками:
// loads B
sync.load(std::memory_order_relaxed);
std::atomic_thread_fence(std::memory_order_acquire);
// memory operations A
Ни одна операция с памятью в A не может быть переупорядочена с любой загрузкой, которая упорядочена до изолированного ограничения захвата.
Автономное ограждение с std::memory_order_acq_rel
упорядочиванием объединяет логику как для приобретения, так и для освобождения ограждений.
// memory operations A
// load A
std::atomic_thread_fence(std::memory_order_acq_rel);
// store B
//memory operations B
Но это может стать невероятно сложным, если вы поймете, что хранилище в A все еще можно переупорядочить с загрузкой в B. Вероятно, следует избегать ограждений Acq / rel в пользу обычных атомарных операций или, что еще лучше, мьютексов.
person
LWimsey
schedule
13.07.2018
std::atomic<>::store
. Не обычная операция записи. - person curiousguy   schedule 13.12.2019