std::atomic_flag是自旋锁最简实现,因其唯一保证无锁且不抛异常,仅含test_and_set()和clear()两个原子操作,底层映射单条CPU指令,无开销、无状态冗余。
std::atomic_flag 为什么是自旋锁的最简实现
因为 std::atomic_flag 是 C++ 标准中唯一保证「无锁(lock-free)」且「不抛异常」的原子类型,它只提供两个操作:test_and_set() 和 clear(),底层通常直接映射为单条 CPU 指令(如 x86 的 XCHG 或 LOCK XCHG),没有内存分配、无构造开销、无虚函数、无状态冗余——这正是轻量级自旋锁需要的全部。
它不支持拷贝、不支持初始化为 true、默认构造即为 clear 状态(false),这些限制不是缺陷,而是刻意为之的设计:避免误用,强制你显式调用 clear() 或使用 ATOMIC_FLAG_INIT(C++17 起已弃用,推荐 std::atomic_flag flag = ATOMIC_FLAG_INIT 或更安全的 std::atomic_flag flag{})。
手写自旋锁时怎么正确使用 test_and_set 和 clear
关键在于:自旋必须用 test_and_set() 的返回值判断是否获取成功,且必须在临界区退出前调用 clear();否则其他线程永远无法获得锁,导致死锁。
-
test_and_set()是原子地「读取当前值 → 设为 true → 返回旧值」,所以首次调用返回false表示抢锁成功 - 必须用
memory_order_acquire(加锁)和memory_order_release(解锁)约束重排,否则编译器或 CPU 可能将临界区外的读写重排进临界区 - 不能在析构函数里无条件
clear():如果对象被 move 构造或未成功加锁,clear()会破坏其他线程的状态
典型实现片段:
立即学习“C++免费学习笔记(深入)”;