Во-первых, я изложу свое понимание семантики освобождения-приобретения, затем я изложу свои сомнения по поводу конкретного случая параллельного программирования на C++ и, наконец, предложу более подходящий случай для иллюстрации этой концепции.
- Мое понимание семантики выпуска-приобретения (см. https://en.cppreference.com/w/cpp/atomic/memory_order)
- После этого сохранения порядок операций чтения или записи в текущем потоке не может быть изменен. .
По сути, это обеспечивает загрузку->сохранение и сохранение->гарантии порядка сохранения в текущем потоке.
- Семантика подразумевает, что запись в атомарную переменную в текущем потоке видна всем потокам, которые получают одну и ту же атомарную переменную одновременно (а не индивидуально). Как только операция выпуска попадает в систему согласованности, она фактически попадает в глобальный порядок, делая ее видимой для всех потоков, а не только для некоторых.
memory_order_acquire:
- Нет чтения и записи в порядок текущего потока можно изменить до этой загрузки.
По сути, это обеспечивает гарантии порядка загрузки->загрузки и загрузки->сохранения в текущем потоке. .
- Любое освобождение атомарной переменной другими потоками будет отслеживаться операцией получения текущего потока (аналогично, а не только некоторым операции).
Вышеизложенное отражает мое понимание семантики выпуска-приобретения.
- Мои сомнения по поводу демонстрации, объясняющей процесс выпуска-приобретения в параллельном программировании на C++ (этот случай, по-видимому, адаптирован из последовательной согласованности демо на cppreference)

Вот демо из книги, объясняющей выпуск-приобретение. В книге утверждается, что последнее утверждение сработает, но после тестирования на x86 и ARM я обнаружил, что оно никогда не срабатывает. Мои сомнения по поводу этого случая основаны не только на том, что я не смог воспроизвести результат, но и на теоретическом фундаменте, который я представил выше. Причины следующие:
- Операция сохранения, соответствующая выпуску, видна всем потокам получения, а не только некоторым. Основываясь на этом понимании, должен существовать глобальный порядок (записи) для X и Y при применении к памяти, гарантирующий, что потоки c и d увидят один и тот же результат; либо x->y, либо y->x, но никогда c не видит x->y, а d видит y->x.
- Вторым доказательством является то, что гарантии выпуска-приобретения:
Store->Store - Загрузить->Сохранить
- Загрузить->Загрузить
- Но пропускает Store->Load
Поэтому, если код в каждом потоке не использует шаблоны Store->Load, мы можем обеспечить глобальный порядок при применении к памяти.
- Исходя из вышеизложенного, я думаю, что следующий пример более разумен для объяснения процесса выпуска-приобретения. Здесь для работы с атомарными переменными используется модель Release-Acquire, а семантика Store->Load создается внутри каждого потока. Поскольку Release-Acquire не гарантирует порядок Store->Load, весьма вероятно, что оба потока не смогут завершить C++, что в конечном итоге приведет к сбою утверждения.

Истинная семантика выпуска-приобретения
Подробнее здесь: https://stackoverflow.com/questions/785 ... quire-in-c