信息发布→ 登录 注册 退出

c++中的std::atomic_flag有什么用_c++最简单的原子类型与自旋锁【并发】

发布时间:2025-12-07

点击量:
std::atomic_flag是最轻量的无锁原子类型,专为自旋锁设计,仅支持test_and_set()和clear()两个原子操作,不支持load/store、拷贝或赋值,必须显式初始化,保证lock-free实现。

c++中的std::atomic_flag有什么用_c++最简单的原子类型与自旋锁【并发】

std::atomic_flag 是 C++ 中最轻量、最底层的原子类型,专为实现自旋锁(spinlock)这类无锁同步原语而设计。它只支持两个操作:test_and_set()(置位并返回旧值)和clear()(清零),且保证这两个操作是原子的、不可中断的。它不提供 load/store 语义,也不支持拷贝或赋值——天生就是“开关型”工具。

为什么需要 atomic_flag?

在多线程环境下,有时需要极简、低开销的互斥控制,比如保护一小段关键代码、实现自定义锁、或构建更复杂的原子结构。mutex 太重(涉及系统调用、上下文切换),而 std::atomic<bool></bool> 虽简单,但无法保证“测试+设置”是单个原子指令(可能被编译器或 CPU 拆分)。atomic_flag 则由标准强制要求必须以**无锁方式实现**(lock-free),通常直接映射到 CPU 的 test-and-setexchangecompare-and-swap 指令,真正做到了最小延迟。

怎么用它写一个自旋锁?

一个典型的、可复用的自旋锁实现如下:

(注意:实际项目中建议优先使用 std::mutex;自旋锁仅适用于临界区极短、且线程数 ≤ CPU 核心数的场景)

Openflow Openflow

一键极速绘图,赋能行业工作流

Openflow 88 查看详情 Openflow
  • ATOMIC_FLAG_INIT 静态初始化(C++17 起可直接用 {} 初始化)
  • 构造时调用 test_and_set(std::memory_order_acquire) 尝试上锁;若返回 false,说明之前是未设置状态,成功获得锁
  • 循环重试直到成功(即“自旋”),每次用 std::this_thread::yield() 提示调度器让出时间片,避免空转霸占 CPU
  • 析构或解锁时调用 clear(std::memory_order_release),确保释放前的写操作对其他线程可见

atomic_flag 和 atomic 的关键区别

  • atomic_flag 一定是 lock-free 的;atomic<bool></bool> 可能退化为内部加锁(罕见,但标准允许)
  • atomic_flag 不支持读取当前值(没有 load()),只能通过 test_and_set() “消耗性读取”
  • atomic_flag 不可拷贝、不可赋值、无默认构造函数(必须显式初始化)
  • 语义更纯粹:它不是“一个布尔原子变量”,而是“一个只能开关一次再清零的原子门闩”

一个最小可行示例

下面代码演示如何用 atomic_flag 保护一个共享计数器递增:

std::atomic_flag lock = ATOMIC_FLAG_INIT;
int counter = 0;

void increment() {
    while (lock.test_and_set(std::memory_order_acquire)) {
        std::this_thread::yield(); // 让出 CPU,减少忙等开销
    }
    ++counter;
    lock.clear(std::memory_order_release);
}

多个线程并发调用 increment() 时,只会有一个线程能“穿过”这个锁,其余线程在 test_and_set() 返回 true 后持续自旋等待,直到锁被释放。

基本上就这些。它不复杂,但容易忽略它的设计初衷——不是用来存状态,而是用来建同步机制的“砖块”。

以上就是c++++中的std::atomic_flag有什么用_c++最简单的原子类型与自旋锁【并发】的详细内容,更多请关注其它相关文章!


相关文章: Golang如何实现状态模式管理对象状态_Golang State模式实现技巧  如何将HTML表格多行数据保存到Google Sheet  内存检查:在VS Code中调试C++时的内存视图  QQ邮箱电脑版登录入口_QQ邮箱官方网站登录平台  聚水潭ERP登录页面入口 聚水潭ERP官网登录界面  荒野行动PC版怎么注册_荒野行动PC版账号注册详细流程图文教程  《刺客信条:影》PS5 Pro和Switch 2画面对比  JUnit5/Mockito:优雅测试内部依赖与异常处理的实践  《噬血代码2》新预告片发布 展示游戏剧情  抖音隐秘迷城小游戏入口_ 抖音冒险解谜小游戏秒玩  解决Bootstrap卡片顶部边距导致背景图下移的问题  Python自定义类排序:解决lambda键值访问TypeError的实践指南  服务端验证_j*ascript输入检查  Go语言:非阻塞式判断标准输入(os.Stdin)是否有数据  J*aScript类型检查_j*ascript代码规范  PHP表单隐藏域数据传递:常见问题与最佳实践  win11如何加载ICC颜色配置文件 Win11校色文件安装与显示器色彩管理【指南】  必由学登录入口 必由学官方网站在线访问链接  单12V-2&#215;6实现为RTX 5090供电750W!甚至都没敢跑分  Python Sounddevice 音频卡顿问题解析与队列数据安全处理  学习通网页版官方登录 超星学习通电脑端入口指南  谷歌邮箱注册显示错误Gmail服务器异常与延迟处理  J*aScript生成器_j*ascript异步迭代  LINUX的I/O重定向是什么_深入理解LINUX中 >、>> 与 < 的区别  漫蛙漫画官方首页 漫蛙2漫画在线阅读入口  J*aScript中赋值与自增运算符的复杂交互与执行机制  Windows10怎么开启存储感知 Windows10系统设置自动清理临时文件释放C盘空间【教程】  Win10文件资源管理器“此电脑”分组怎么关 Win10恢复经典视图【技巧】  如何修改开机登录密码_Windows账户安全设置超详细教程【必学】  高德地图总提示网络异常怎么办 高德地图离线导航设置与网络排查方法  Lar*el Eloquent:高效统计带条件关联模型的数量  QQ邮箱登录首页官网地址2026 QQ邮箱官方网页入口  自动化J*a应用中GitHub CLI或REST API的认证与交互  MAC如何安全彻底地删除文件_MAC使用终端命令确保文件无法被恢复  韩剧圈正版入口页面_韩剧圈官网登录链接  如何在 Windows 11 中启动游戏手柄设置  蓝湖怎样用切图标注提对接效率_蓝湖用切图标注提对接效率【设计对接】  学习通在线学习平台 学习通网页版直接进入课程中心  126邮箱账号注册 电脑版登录入口  Python异步编程实践:使用Binance API构建实时交易数据流  提升屏幕阅读器对“m”时间单位的播报准确性:HTML与CSS组合解决方案  蛙漫漫画免费阅读入口_蛙漫官方正版无广告纯净版  俄罗斯搜索引擎Yandex指南 附2025年免登录官网入口  word中如何让数字纵向排列_Word数字纵向排列方法  c++ 命名空间怎么用 c++ namespace使用指南  解决PHP集成HTML后CSS和图片路径加载问题的指南  抖音网页版企业服务中心登录入口_抖音网页版企业登录平台  深入理解Go语言中Map值与方法接收器的交互:为什么需要临时变量  俄罗斯Yandex免登录入口_Yandex搜索引擎官网一键直达  KFC早餐时段怎么领特惠代码_KFC早餐订餐优惠代码获取与使用说明 

在线客服
服务热线

服务热线

4008988990

微信咨询
二维码
返回顶部
×二维码

截屏,微信识别二维码

打开微信

微信号已复制,请打开微信添加咨询详情!