Что такое std::atomic?



Я понимаю, что std::atomic<> является атомарным объектом. Но атомный до какой степени? В моем понимании операция может быть атомной. Что именно подразумевается под атомизацией объекта? Например, если есть два потока одновременно выполнив следующий код:



a = a + 12;


тогда вся операция (скажем add_twelve_to(int)) атомный? Или изменения, внесенные в переменную atomic (so operator=())?

720   2  

2 ответов:

каждый экземпляр и полная специализация std:: atomic представляет тип, на котором могут одновременно работать разные потоки (их экземпляры), не вызывая неопределенного поведения:

объекты атомной типы являются только объекты C++, которые свободны от гонок данных, то есть, если один поток пишет в атомарный объект, а другой поток читает из него, поведение четко определено.

кроме того, доступ к атомной объекты могут создавать межпоточная синхронизация и порядок неатомарный доступ к памяти, как указано std::memory_order.

std::atomic<> операции обертывания, которые в pre-C++ 11 раз должны были выполняться с использованием (например) блокировать функции С MSVC или атомная bultins в случае GCC.

и std::atomic<> дает вам больше контроля, позволяя различные заказы память, которые определяют синхронизацию и порядок ограничения. Если вы хотите узнать больше о c++ 11 atomics and memory model, эти ссылки могут быть полезны:

обратите внимание, что для типичных случаев использования вы, вероятно, будете использовать перегружать арифметические операторы или еще один набор из них:

std::atomic<long> value(0);
value++; //This is an atomic op
value += 5; //And so is this

поскольку синтаксис оператора не позволяет указать порядок памяти, эти операции будут выполняться с помощью std::memory_order_seq_cst, так как это порядок по умолчанию для всех атомарных операций в C++ 11. Оно гарантирует последовательную последовательность (полный глобальный приказывать) между все атомарные операции.

В некоторых случаях, однако, это может не потребоваться (и ничего не приходит бесплатно), так что вы можете использовать более явном виде:

std::atomic<long> value {0};
value.fetch_add(1, std::memory_order_relaxed); // Atomic, but there are no synchronization or ordering constraints
value.fetch_add(5, std::memory_order_release); // Atomic, performs 'release' operation

теперь ваш пример:

a = a + 12;

не будет оцениваться до одного атомарного op: это приведет к a.load() (что само по себе является атомарным), затем добавление между этим значением и 12 и a.store() (кроме атомной) конечного результата. Как я уже отмечал ранее, std::memory_order_seq_cst будут использованы здесь.

однако, если вы пишите a += 12, это будет атомарная операция (как я уже отмечал ранее) и примерно эквивалентна a.fetch_add(12, std::memory_order_seq_cst).

что касается вашего комментария:

обычный int имеет атомные нагрузки и магазины. Какой смысл обертывать его с atomic<>?

ваше утверждение верно только для архитектур, которые обеспечивают такую гарантию атомарности для магазинов и/или нагрузок. Есть архитектуры, которые не делают этот. Кроме того, обычно требуется, чтобы операции выполнялись по адресу, выровненному по word-/dword, чтобы быть атомарным std::atomic<> Это что-то, что гарантированно будет атомарным на каждый

Я понимаю, что std::atomic<> делает объект атомной.

это вопрос перспективы... вы не можете применить его к произвольным объектам и сделать их операции атомарными, но можно использовать предоставленные специализации для (большинства) интегральных типов и указателей.

a = a + 12;

std::atomic<> не упрощает (использует шаблонные выражения) это до одной атомной операции, вместо

Comments

    Ничего не найдено.