Что такое std::atomic в C++?

«Что такое std::atomic в C++?» — вопрос из категории Многопоточность, который задают на 25% собеседований C/C++ Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

std::atomic — это шаблонный класс из стандартной библиотеки C++ (<atomic>), который обеспечивает атомарный (неделимый) доступ к переменной в многопоточном контексте. Это означает, что операции чтения, записи и модификации над такой переменной защищены от состояний гонки (data races).

Основные принципы:

  • Атомарность: Операции, такие как load, store, fetch_add, выполняются как единое целое относительно других потоков.
  • Порядок памяти: Позволяет задавать модель памяти (memory_order), контролируя видимость изменений между потоками и строгость упорядочивания операций.
  • Применимость: Специализирован для базовых типов (int, bool, указателей), но может быть использован с пользовательскими типами, если они тривиально копируемы (с некоторыми ограничениями на производительность).

Пример: потокобезопасный счётчик

#include <atomic>
#include <iostream>
#include <thread>
#include <vector>

std::atomic<int> counter{0};

void increment(int iterations) {
    for (int i = 0; i < iterations; ++i) {
        // Атомарно добавляем 1. Используем relaxed ordering,
        // так как важен только атомарный инкремент.
        counter.fetch_add(1, std::memory_order_relaxed);
    }
}

int main() {
    std::thread t1(increment, 1000000);
    std::thread t2(increment, 1000000);
    t1.join();
    t2.join();
    // Гарантированно выведет 2000000, состояние гонки исключено.
    std::cout << "Final counter value: " << counter.load() << 'n';
    return 0;
}

Почему это важно: Использование std::atomic для простых операций часто эффективнее, чем блокировка мьютексом, так как реализуется через атомарные инструкции процессора.