0

0

C++中的std::atomic_flag是什么?(如何实现简易自旋锁)

穿越時空

穿越時空

发布时间:2026-02-10 14:21:10

|

815人浏览过

|

来源于php中文网

原创

std::atomic_flag 是专为自旋锁设计的无锁原子布尔标志,仅提供 test_and_set() 和 clear(),不支持 load/store,必须显式初始化(如 ATOMIC_FLAG_INIT),不可用 bool 赋值。

c++中的std::atomic_flag是什么?(如何实现简易自旋锁)

std::atomic_flag 是什么,为什么不能直接用 bool

它是一个无锁、无竞争、保证原子性的布尔标志,底层通常映射到单条 CPU 指令(如 x86 的 XCHGTEST_AND_SET),比 std::atomic 更轻量——关键在于它**不提供 load/store 语义,只提供 test_and_set()clear()**。很多初学者误以为它是“更小的 atomic”,其实它设计初衷就是做自旋锁原语,连默认构造都不保证清零(C++20 前必须用 ATOMIC_FLAG_INIT 显式初始化)。

常见错误现象:std::atomic_flag flag; 在 C++17 及之前会触发未定义行为,因为未初始化;flag.test_and_set() 返回 true 却没清掉,导致死锁。

  • 必须用 ATOMIC_FLAG_INIT(C++17 起可改用 constexpr 默认构造,但需确认编译器支持)
  • 不能用 = true{true} 初始化 —— 它没有从 bool 的隐式转换
  • test_and_set() 总是返回旧值,且带默认内存序 memory_order_seq_cst;高频自旋时建议显式降为 memory_order_acquire(设)和 memory_order_release(清)

怎么用 std::atomic_flag 实现一个最小可行自旋锁

核心逻辑就两行:循环调用 test_and_set() 直到返回 false(说明抢到了锁),临界区结束后调用 clear()。但它不是“拿来即用”的锁,得自己管生命周期、不可重入、不阻塞线程。

使用场景:短临界区(纳秒~微秒级)、已知争用极低、或作为其他锁(如 mutex)内部的 fast-path。

立即学习C++免费学习笔记(深入)”;

WPS灵犀
WPS灵犀

WPS灵犀是WPS推出的一款AI智能办公和学习助手

下载
struct spinlock {
    std::atomic_flag flag = ATOMIC_FLAG_INIT;
    void lock() {
        while (flag.test_and_set(std::memory_order_acquire)) {
            // 避免忙等耗尽资源,可加 pause 指令提示 CPU
            __builtin_ia32_pause(); // GCC/Clang x86
        }
    }
    void unlock() {
        flag.clear(std::memory_order_release);
    }
};
  • __builtin_ia32_pause() 不是必需,但能显著降低功耗和总线争用;ARM 上对应 __builtin_arm_yield()
  • 别在 lock() 里 throw 异常 —— 否则 unlock() 永远不执行,锁永远挂起
  • 不能拷贝、不能 move,std::atomic_flag 是 trivially copyable 但禁止拷贝赋值

为什么不用 std::atomic 替代 std::atomic_flag

可以,但没必要,而且容易出错。最直接的问题是:std::atomicexchange(true) 不等价于 test_and_set() —— 前者返回的是旧值,但语义上不承诺“设置并获取”在单指令中完成;某些平台可能生成多条指令,失去原子性保证(尽管实践中通常安全,但标准不保)。

性能影响:在 ARMv8 或 RISC-V 等弱内存模型平台上,std::atomic_flag 可被编译为单条 swpamoswap 指令,而 atomic::exchange() 可能退化为 LL/SC 循环,失败重试开销更大。

  • 兼容性:所有 C++11 实现都必须支持 std::atomic_flag,但对 std::atomic 的 lock-free 实现无强制要求(可用 is_lock_free() 检查)
  • 别写 flag.store(true) —— std::atomic_flag 根本不提供 store 接口
  • 调试时注意:gdb 可能无法直接打印 std::atomic_flag 值,得靠 flag.test_and_set() + flag.clear() 临时探测

实际部署时最容易忽略的三个点

自旋锁看着简单,但线上一出问题往往难复现、难定位。

  • 忘了关中断或禁调度 —— 在内核态或实时线程中,自旋期间若被抢占,可能造成优先级反转或看门狗超时
  • 临界区里调用了可能 sleep 的函数(如 malloc、printf、系统调用)—— 自旋锁绝不该出现在可能阻塞的上下文中
  • 没考虑 NUMA:跨 socket 自旋会引发大量缓存行 bouncing,std::atomic_flag 在不同 socket 上的 test_and_set() 延迟可能差 3~5 倍

真正用它的地方,往往连 RAII 封装都省了,直接裸写 lock(); /* ... */ unlock(); —— 因为任何异常路径都得手动确保 unlock,封装反而增加误用风险。

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
printf用法大全
printf用法大全

php中文网为大家提供printf用法大全,以及其他printf函数的相关文章、相关下载资源以及各种相关课程,供大家免费下载体验。

76

2023.06.20

fprintf和printf的区别
fprintf和printf的区别

fprintf和printf的区别在于输出的目标不同,printf输出到标准输出流,而fprintf输出到指定的文件流。根据需要选择合适的函数来进行输出操作。更多关于fprintf和printf的相关文章详情请看本专题下面的文章。php中文网欢迎大家前来学习。

293

2023.11.28

printf用法大全
printf用法大全

php中文网为大家提供printf用法大全,以及其他printf函数的相关文章、相关下载资源以及各种相关课程,供大家免费下载体验。

76

2023.06.20

fprintf和printf的区别
fprintf和printf的区别

fprintf和printf的区别在于输出的目标不同,printf输出到标准输出流,而fprintf输出到指定的文件流。根据需要选择合适的函数来进行输出操作。更多关于fprintf和printf的相关文章详情请看本专题下面的文章。php中文网欢迎大家前来学习。

293

2023.11.28

硬盘接口类型介绍
硬盘接口类型介绍

硬盘接口类型有IDE、SATA、SCSI、Fibre Channel、USB、eSATA、mSATA、PCIe等等。详细介绍:1、IDE接口是一种并行接口,主要用于连接硬盘和光驱等设备,它主要有两种类型:ATA和ATAPI,IDE接口已经逐渐被SATA接口;2、SATA接口是一种串行接口,相较于IDE接口,它具有更高的传输速度、更低的功耗和更小的体积;3、SCSI接口等等。

1346

2023.10.19

PHP接口编写教程
PHP接口编写教程

本专题整合了PHP接口编写教程,阅读专题下面的文章了解更多详细内容。

298

2025.10.17

php8.4实现接口限流的教程
php8.4实现接口限流的教程

PHP8.4本身不内置限流功能,需借助Redis(令牌桶)或Swoole(漏桶)实现;文件锁因I/O瓶颈、无跨机共享、秒级精度等缺陷不适用高并发场景。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2202

2025.12.29

java接口相关教程
java接口相关教程

本专题整合了java接口相关内容,阅读专题下面的文章了解更多详细内容。

34

2026.01.19

包子漫画网页版入口与全集阅读指南_正版免费漫画快速访问方法
包子漫画网页版入口与全集阅读指南_正版免费漫画快速访问方法

本专题汇总了包子漫画官网和网页版入口,提供最新章节抢先看方法、正版免费阅读指南,以及稳定访问方式,帮助用户快速直达包子漫画页面,无广告畅享全集漫画内容。

18

2026.02.10

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
C# 教程
C# 教程

共94课时 | 9万人学习

C 教程
C 教程

共75课时 | 4.6万人学习

C++教程
C++教程

共115课时 | 16.8万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号