Другой разработчик показал мне следующий фрагмент:
std::atomic_flag lock;
// ...
while (lock.test_and_set(std::memory_order::acquire)) {}
// critical section
lock.clear(std::memory_order::release);
Я не понимаю, что здесь означает указание acquire в качестве порядка памяти.
Это неявно тот же порядок, что и acq_rel, или это acquire для операции загрузки и seq_cst (по умолчанию) для операции сохранения в рамках этой операции чтения-изменения-записи?
std::atomic_flag::test_and_set не имеет предварительных условий, и просто сказано, что:
На память влияет значение
order.
Это ничего не проясняет для меня. Что, если order — это acquire? Как тогда пострадает магазин, а?





Порядки памяти описываются (только) с точки зрения их влияния на синхронизацию и последовательность.
Атомарная операция
A, выполняющая операцию освобождения атомарного объектаM, синхронизируется с атомарной операциейB, которая выполняет операцию полученияMи получает свое значение из любого побочного эффекта в последовательности освобождения, возглавляемойA.
Влияние acquire на «тестовую» часть test_and_set очевидно. Что касается его влияния на «установочную» часть? Ну, у него его нет. Как и в случае с relaxed, стандарт просто не предоставляет никаких полезных гарантий. Итак, это эквивалентно чему-то вроде memory_order::acq_relaxed. Компилятор может перемещать чтение/запись вниз за test_and_set, но не вверх.
В стандарте это можно прочитать так: это операция получения, но, по упущению, это не операция освобождения (поскольку об этом никогда не говорится) и она не является последовательной последовательностью.
За пределами формализма C++ рассмотрим машину LL/SC, такую как ARMv8.0: на стороне загрузки используется
ldaxr(эксклюзивная загрузка приобретения), но на стороне хранилища просто нужна атомарность, а не упорядочивание, поэтомуstxrнеstlxr. godbolt.org/z/M95EfsMd6 . Связанный: Для целей упорядочения атомарное чтение-изменение-запись — это одна операция или две?