Единственный атомарный тип, для которого гарантируется свойство 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