std::atomic и порядок работы с памятью
Используйте std::atomic с подходящим порядком работы с памятью для корректности и скорости.
«std::atomic и порядок работы с памятью» — бесплатный урок C++ Academy на CoddyKit. Это урок 1 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения C++ Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс C++ Academy содержит 4 уроков всего.
За пределами мьютексов
Блокировки последовательно предоставляют доступ — это просто и надёжно, но они ограничивают пропускную способность. std::atomic предоставляет строительные блоки без блокировок для высокопроизводительного параллельного кода.
Основы std::atomic
std::atomic<T> оборачивает значение и поддерживает атомарные операции чтения, изменения и записи.
#include <atomic>
std::atomic<int> counter{0};
counter.fetch_add(1); // atomic increment
int v = counter.load();
counter.store(0);Удобные операторы
Для арифметических типов обычные операторы являются атомарными.
std::atomic<int> n{0};
++n; // atomic increment
n += 5; // atomic add
int v = n; // atomic loadПочему атомарные операции сложны
CPU может переупорядочивать операции с памятью между ядрами. Порядок памяти определяет, какие перестановки разрешены.
Порядки памяти
Пять распространённых порядков:
memory_order_relaxed— атомарность без упорядочиванияmemory_order_acquire— используется в паре с release; запрет перестановки после операцииmemory_order_release— используется в паре с acquire; запрет перестановки перед операциейmemory_order_acq_rel— оба ограниченияmemory_order_seq_cst— последовательная согласованность (по умолчанию)
Последовательная согласованность: безопасный вариант по умолчанию
Порядок seq_cst по умолчанию ведёт себя интуитивно: кажется, что все атомарные операции выполняются в едином глобальном порядке. Он медленнее ослабленных порядков, но его проще анализировать.
Сочетание acquire и release
Используйте release в производителе и acquire в потребителе. После acquire становятся видимыми все записи, выполненные до соответствующего release.
std::atomic<bool> ready{false};
int data = 0;
// producer
data = 42;
ready.store(true, std::memory_order_release);
// consumer
while (!ready.load(std::memory_order_acquire));
std::cout << data; // sees 42Ослабленный порядок
Атомарные операции с ослабленным порядком обеспечивают атомарность, то есть не допускают разорванных чтений, но разрешают любое переупорядочивание. Используйте их для простых счётчиков, когда порядок не имеет значения.
Сравнение и обмен
Основа большинства алгоритмов без блокировок. compare_exchange_strong(expected, desired) атомарно обновляет значение только в том случае, если текущее значение равно expected.
std::atomic<int> a{10};
int expected = 10;
bool ok = a.compare_exchange_strong(expected, 20);
// if true, a is now 20; otherwise expected holds the actual current valueСлабый и сильный CAS
compare_exchange_weak может ошибочно завершиться неудачей даже при совпадении значений. Используйте его внутри циклов, поскольку на некоторых платформах он эффективнее; вне циклов используйте strong.
Без блокировок и без ожидания
Две гарантии продвижения:
- Без блокировок — хотя бы один поток в любой момент продвигается
- Без ожидания — каждый поток продвигается за ограниченное время
Когда использовать атомарные операции
Атомарные операции не всегда быстрее мьютексов. Используйте их, когда критический путь можно сделать простым: для счётчиков, флагов и простых состояний. Для сложного общего состояния мьютексы обычно безопаснее и понятнее.
Быстрая проверка
Какой порядок памяти предоставляет самые сильные гарантии, но при этом является самым медленным?
Итоги
std::atomic предоставляет примитивы без блокировок с явным управлением порядком памяти. По умолчанию выбирайте memory_order_seq_cst; используйте пары acquire/release в шаблонах «производитель — потребитель»; применяйте relaxed только для неупорядоченных атомарных операций, например для счётчиков.
Часто задаваемые вопросы
Урок «std::atomic и порядок работы с памятью» бесплатный?
Да — полный текст урока «std::atomic и порядок работы с памятью» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс C++ Academy, подпишись на CoddyKit PRO. Курс C++ Academy содержит 4 уроков всего.
Чему я научусь в уроке «std::atomic и порядок работы с памятью»?
Используйте std::atomic с подходящим порядком работы с памятью для корректности и скорости. Ты практикуешь C++ Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.
Нужен ли мне опыт, чтобы начать C++ Academy?
Предыдущий опыт не требуется. C++ Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 1 из 4.
Сколько времени занимает урок «std::atomic и порядок работы с памятью»?
Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.
Можно ли писать и запускать код в этом уроке C++ Academy?
Да. Каждый урок C++ Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.
Все уроки этого курса
- std::atomic и порядок работы с памятью
- Сравнение и обмен: шаблоны CAS
- Реализация очереди без блокировок
- Опасные указатели и проблема ABA