Единственный атомарный тип, для которого гарантируется свойство lock-free — это std::atomic_flag. Все специализации std::atomic<T> могут использовать мьютексы для опеспечения атомарности операций.

Подробное описание Ссылка на заголовок

std::atomic_flag (не путать с std::atomic<bool>) — единственный атомарный тип, для которого стандарт C++ гарантирует свойство lock-free:

Операции над объектом atomic_flag должны быть lock-free.

Строгое определние lock-free операции: если несколько потоков выполняют lock-free операции, хотя бы один из потоков в конце концов завершит выполнение операции, вне зависимости от состояния других потоков. Таким образом, если владеющий lock-ом поток был прерван, все потоки, ожидающие этот lock, не смогут завершить выполнение операции. Это значит, что lock-free операции не могут использовать блокировки.

Примечание: lock-free операция всегда обладает более слабым свойством obstruction-free, но не обязательно обладает более строгим свойством wait-free. Хорошая статья о данных свойствах на 1024cores.

Гарантия lock-free предоставляется только для std::atomic_flag. Другие атомарные типы могут не быть lock-free, и их операции могут быть реализованы с использованием внутренних блокировок (и, следовательно, могут блокироваться). Однако на практике многие специализации std::atomic<T> будут также lock-free. Чтобы проверить, является ли данная специализация std::atomic<T> lock-free на целевой платформе, используйте метод is_lock_free() или static constexpr std::atomic<T>::is_always_lock_free. Зачем нужны оба способа? Теоретически is_always_lock_free может быть false, в то время как для конкретного объекта is_lock_free() вернёт true. Иными словами, lock-free свойство не может быть гарантировано для некоторых специализаций std::atomic, в то время как конкретные объекты могут обладать этим свойством. Так может произойти из-за требований платформы, соответствие которым может быть проверено только в ходе выполнения. Например, платформа может требовать выравнивания для атомарного объекта; неправильно выровненный атомарный объект не будет lock-free.

Почему std::atomic_flag единственный тип с гарантией lock-free? N2427 поясняет:

Операции с atomic_flag должны выполняться без блокировок. Тип atomic_flag — это минимальный аппаратно реализуемый тип, необходимый для соответствия этому стандарту. Остальные типы могут быть эмулированы с помощью atomic_flag, хотя при этом их свойства будут далеки от оптимальных.

Пример Ссылка на заголовок

К примеру, процессор может не поддерживать атомарные операции для достаточно крупного типа T в шаблоне std::atomic<T>, поэтому для обеспечения атомарности реализация может прибегнуть к блокировкам:

#include <atomic>
#include <iostream>

int main() {
    struct A{int x[2];};
    struct B{int x[20];};
    std::cout << std::atomic<A>::is_always_lock_free <<
        std::atomic<B>::is_always_lock_free;
}

Возможный вывод:

10