最新下载
热门教程
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
C++中使用std::atomic_flag实现简单的锁
时间:2026-06-19 08:29:47 编辑:袖梨 来源:一聚教程网
不是必须,但C++17起推荐用std::atomic_flag flag{}值初始化;ATOMIC_FLAG_INIT已弃用,漏初始化会导致未定义行为;test_and_set()返回false表示获取锁成功,需配对使用memory_order_acquire和release;它不支持load或operator==,仅提供test_and_set()和clear()。
std::atomic_flag 初始化必须用 ATOMIC_FLAG_INIT 吗?
不是必须,但不推荐手动初始化。C++17 起 ATOMIC_FLAG_INIT 已弃用,正确做法是用值初始化:std::atomic_flag flag{};。如果写成 std::atomic_flag flag = ATOMIC_FLAG_INIT;,在 C++17+ 编译会报错或警告;若漏掉初始化(比如只声明 std::atomic_flag flag;),其内部状态未定义,test_and_set() 行为不可预测。
常见错误现象:程序偶发死锁或 flag.test_and_set() 返回 false 却没真正设为 true——基本就是未正确初始化。
- 始终用
std::atomic_flag flag{};(零初始化) - 不要赋值初始化,也不要依赖默认构造(它不保证清零)
- 若需运行时重置,用
flag.clear(std::memory_order_relaxed);
如何用 test_and_set() 实现忙等待锁?
test_and_set() 是原子地“读取当前值并设为 true”,返回旧值。返回 false 表示此前未被占用,当前线程成功获取锁;返回 true 表示已被占用,需等待。
典型实现就是循环调用直到成功:
立即学习“C++免费学习笔记(深入)”;
while (flag.test_and_set(std::memory_order_acquire)) { // 可选:短暂让出 CPU,避免过度自旋 std::this_thread::yield();}
注意内存序:std::memory_order_acquire 保证后续读写不会被重排到锁获取之前;释放锁时必须配对使用 std::memory_order_release。
- 获取锁用
test_and_set(std::memory_order_acquire) - 释放锁用
flag.clear(std::memory_order_release) - 避免用
relaxed—— 它无法防止指令重排,导致临界区逻辑错乱 -
yield()不是必须,但在单核或高竞争场景下能降低 CPU 占用
为什么不能直接用 flag == false 判断是否空闲?
std::atomic_flag 没有 operator==,也不支持直接读取布尔值。它只提供 test_and_set() 和 clear() 两个原子操作。试图写 if (!flag) 或 flag.load() 会编译失败。
这是设计使然:避免“检查再设置”这种非原子的竞态操作。如果你需要“只读检查”,必须用 test_and_set() 并接受它会改变状态 —— 所以真正的“尝试获取”只能靠循环 + 原子操作完成。
- 没有
load()、没有operator bool、没有is_lock_free()的公开访问(虽然内部是 lock-free) - 所谓“检查是否空闲”本质就是一次
test_and_set()尝试,失败即空闲(返回 false),成功即已占(返回 true) - 想实现 try_lock,就只调用一次
test_and_set(),不循环
std::atomic_flag 实现的锁有哪些局限?
它是最轻量的原子锁原语,但功能极简:无所有权、不支持递归、不阻塞线程、不通知等待者。适用于短临界区、低竞争、对延迟敏感的场景(如无锁数据结构内部同步),不适合通用互斥需求。
容易踩的坑包括:忘记释放锁导致死锁;在异常路径中未调用 clear();用在需要条件变量配合的场景却硬套 busy-wait。
- 没有析构自动释放机制 —— 必须显式调用
clear(),建议用 RAII 封装(如自定义scoped_lock类) - 不保证公平性,新线程可能永远抢不过已在自旋的老线程
- 在高负载下自旋浪费 CPU,此时应考虑
std::mutex或更高级同步原语
真正用好它,关键不是“怎么写”,而是想清楚:这个临界区是否足够短、是否确定不会抛异常、是否真的不能接受系统调用开销。
相关文章
- 刀剑缭乱2026公测兑换码大全一览 07-05
- 崩坏星穹铁道4.0卡池7个新角色一览 07-05
- 明日方舟终末地开服工业蓝图一览 工业蓝图作用与使用思路解析 07-05
- 原神梦之树怎么开启 梦之树开启条件 07-05
- 帕瓦勇者传说持续伤害阵容搭配推荐 07-05
- 明日方舟:终末地全新玩法 蚀像寻遗怎么玩介绍 07-05