Что такое std::atomic?
Я понимаю, что std::atomic<> является атомарным объектом. Но атомный до какой степени? В моем понимании операция может быть атомной. Что именно подразумевается под атомизацией объекта? Например, если есть два потока одновременно выполнив следующий код:
a = a + 12;
тогда вся операция (скажем add_twelve_to(int)) атомный? Или изменения, внесенные в переменную atomic (so operator=())?
2 ответов:
каждый экземпляр и полная специализация std:: atomic представляет тип, на котором могут одновременно работать разные потоки (их экземпляры), не вызывая неопределенного поведения:
объекты атомной типы являются только объекты C++, которые свободны от гонок данных, то есть, если один поток пишет в атомарный объект, а другой поток читает из него, поведение четко определено.
кроме того, доступ к атомной объекты могут создавать межпоточная синхронизация и порядок неатомарный доступ к памяти, как указано
std::memory_order.
std::atomic<>операции обертывания, которые в pre-C++ 11 раз должны были выполняться с использованием (например) блокировать функции С MSVC или атомная bultins в случае GCC.и
std::atomic<>дает вам больше контроля, позволяя различные заказы память, которые определяют синхронизацию и порядок ограничения. Если вы хотите узнать больше о c++ 11 atomics and memory model, эти ссылки могут быть полезны:
- атомика C++ и упорядочение памяти
- сравнение: Lockless Программирование с атомикой в C++ 11 против мьютекса и RW-locks
- C++11 вводит стандартизированную модель памяти. Что это значит? И как это повлияет на программирование на C++?
- параллелизма в C++11
обратите внимание, что для типичных случаев использования вы, вероятно, будете использовать перегружать арифметические операторы или еще один набор из них:
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