std::atomic::exchange(true) 能“凑合”当锁用,因其是单次原子RMW操作,返回旧值判断抢锁成功,但仅适用于低竞争、一次性抢占场景;需配对使用acquire加锁与release解锁,否则可见性失效;相比std::atomic_flag::test_and_set(),后者更轻量、强制lock-free且防误用。

能实现,但不是最优解;它适合低竞争、一次性抢占场景,高并发下容易踩内存序和平台兼容性坑。
std::atomic::exchange(true) 为什么能“凑合”当锁用
因为 exchange(true, std::memory_order_acquire) 是单次原子 RMW 操作:不管当前值是什么,都写入 true,并返回旧值。若返回 false,说明此前未被占用,抢锁成功。
- 它不依赖“读-比-写”流程,x86 下通常编译为单条
XCHG指令,无伪失败、无重试开销 - 适用于初始化阶段的单次抢占、关机信号置位等“只管换掉”的场景
- 但不能用于需要条件判断的逻辑(比如“仅当空闲才设为占用”),否则会覆盖刚释放的状态
必须配对使用的内存序:acquire 加锁 + release 解锁
只在 exchange() 里加 std::memory_order_acquire 不够——临界区内的写操作可能被重排到锁外,其他线程看不到。
- 加锁用:
flag_.exchange(true, std::memory_order_acquire) - 解锁必须用:
flag_.store(false, std::memory_order_release),不能只写flag_ = false - 漏掉
std::memory_order_release是最常被忽略的坑,会导致数据可见性失效 - 别用
std::memory_order_relaxed替代,它无法建立同步边界
比 std::atomic_flag::test_and_set() 差在哪
std::atomic_flag 是 C++ 标准中唯一强制 lock-free 的类型,而 std::atomic<bool></bool> 在某些嵌入式平台或旧编译器上可能退化为互斥锁模拟,性能断崖下跌。
-
std::atomic_flag::test_and_set(std::memory_order_acquire)语义更贴近硬件,无需手动选序(默认seq_cst) - 它天然禁止拷贝/赋值,防误用;
test_and_set()行为与exchange(true)一致,但更轻量 - 如果你只是要一个轻量、一次性、无等待的锁,
std::atomic_flag是更安全、更可移植的选择 - 别写
std::exchange(flag_, true)——那是<utility></utility>里的非原子函数,完全无效
自旋时不做退让会吃满 CPU
空转循环不加任何退让机制,会让线程在核上持续发射 XCHG,不仅浪费算力,还加剧 cache line 争用。
- 建议在循环体内加
_mm_pause()(x86)或std::this_thread::yield()(跨平台) -
_mm_pause()不是系统调用,开销极小,能提示 CPU 当前是自旋等待,降低功耗和总线压力 - 高竞争下,纯
exchange自旋锁的 cache line 争用比compare_exchange_weak更重,这点容易被忽略
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











