fetch_add с порядком памяти acq_rel

Рассмотрим

std::atomic<int> x(0);

Предположим, у меня есть функция, выполняющая следующее:

int x_old = x.fetch_add(1,std::memory_order_acq_rel);

На основе описание для упорядочения памяти:

memory_order_relaxed Расслабленная операция: нет никаких ограничений синхронизации или упорядочения, требуется только атомарность этой операции (см. Расслабленное упорядочение ниже)

memory_order_consume Операция загрузки с этим порядком памяти выполняет операцию потребления в уязвимом месте памяти: никакие операции чтения или записи в текущем потоке в зависимости от загруженного в данный момент значения не могут быть переупорядочены перед этой загрузкой. Запись в зависимые от данных переменные в других потоках, которые выпускают ту же атомарную переменную, видна в текущем потоке. На большинстве платформ это влияет только на оптимизацию компилятора (см. Порядок выпуска-потребления ниже)

memory_order_acquire Операция загрузки с этим порядком памяти выполняет операцию получения в уязвимом месте памяти: никакие операции чтения или записи в текущем потоке не могут быть переупорядочены до этой загрузки. Все записи в других потоках, которые выпускают одну и ту же атомарную переменную, видны в текущем потоке (см. Порядок выпуска-получения ниже)

memory_order_release Операция сохранения с этим порядком памяти выполняет операцию освобождения: после этого сохранения никакие операции чтения или записи в текущем потоке не могут быть переупорядочены. Все записи в текущем потоке видны в других потоках, которые получают одну и ту же атомарную переменную (см. Порядок упорядочения Release-Acquire ниже), и записи, которые переносят зависимость в атомарную переменную, становятся видимыми в других потоках, которые используют тот же атомарный (см. Release-Consume). порядок ниже).

memory_order_acq_rel Операция чтения-изменения-записи с этим порядком памяти является и операцией получения, и операцией освобождения. Никакие операции чтения или записи в памяти в текущем потоке не могут быть переупорядочены ни до, ни после этого хранилища. Все записи в других потоках, которые выпускают одну и ту же атомарную переменную, видны до модификации, а модификация видна в других потоках, которые получают ту же атомарную переменную.

memory_order_seq_cst Любая операция с этим порядком памяти является и операцией получения, и операцией освобождения, плюс существует единый общий порядок, в котором все потоки наблюдают все модификации в одном и том же порядке (см. Последовательно-последовательный порядок ниже)

Возможно ли для двух разных потоков получать одинаковые x_old значение 0? Или они гарантированно выполнятся таким образом, чтобы x_old 0 для только одного из них и 1 для другого.

Если это правда, что x_old может быть 0 для них обоих, делает изменение порядка памяти в std::memory_order_seq_cst гарантировать уникальность x_old?

4

Решение

Возможно ли для двух разных потоков получить одинаковое значение x_old, равное 0?

Это невозможно, потому что операция атомное. Это или происходит полностью, или не происходит вообще.

Заказ касается предшествующих / следующих грузов / магазинов, и так как у вас их нет, заказ здесь не имеет значения. Другими словами, x.fetch_add(1, std::memory_order_relaxed); имеет такой же эффект здесь.

На нынешнем x86 это то же самое lock xadd инструкция независимо от memory_order, lock Префикс обеспечивает как атомарность, так и порядок. За memory_order_relaxed упорядочивающая часть lock не нужно

6

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]