讲师中心 微信公众号
AI工具推荐 视频效率加速

C++ std::atomic::wait与notify实现高效的事件通知无锁同步机制 _ 源码【详解】

胖婷小哥_6970

胖婷小哥_6970

发布时间:2026-05-10 15:05:20

|

711人浏览过

|

来源于php中文网

原创

应使用满足平凡可复制、大小适配且平台支持的原子类型,配对 release-acquire 内存序,循环检查状态以避免通知丢失,并约束非原子数据访问顺序,同时确认目标平台原生支持 wait/notify。

c++ std::atomic::wait与notify实现高效的事件通知无锁同步机制 _ 源码【详解】

如果您在实现多线程事件通知时希望避免互斥锁开销、消除上下文切换延迟,并确保等待行为严格绑定于原子变量状态变化,则可能遇到 std::atomic::wait 与 notify 调用无效、线程永不唤醒或读取到脏数据等问题。以下是解决此问题的步骤:

一、确保原子类型满足可等待前提

std::atomic::wait 仅对特定平凡可复制(trivially copyable)且平台支持的原子类型生效,如 std::atomic、std::atomic、std::atomic 等;若使用 std::atomic<:string> 或未对齐的自定义结构体,调用 wait 将退化为自旋或触发未定义行为。

1、确认模板参数 T 满足 std::is_trivially_copyable_v,且 sizeof(T) ≤ sizeof(void*)

2、避免使用 std::atomic 或 std::atomic,因其在多数标准库实现中不支持 wait/notify

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

3、显式声明原子变量时采用标准整型别名,例如使用 std::atomic_uint32_t 而非 std::atomic(确保 ABI 兼容)

二、正确配对 memory_order 与 store/wait 语义

wait 操作依赖内存序保证写入对等待线程可见;若 notify 前仅用 memory_order_relaxed 存储,唤醒可能丢失,因写入未同步到其他 CPU 缓存行。

1、在通知线程中执行 store 时必须使用至少 memory_order_release 顺序

2、在等待线程中调用 wait 前,必须先执行一次带 memory_order_acquire 或更强序的 load,以获取最新值并建立同步点

3、将 load 结果赋值给局部变量 expected,再传入 wait,禁止直接传入字面量如 flag.wait(0)

三、规避通知丢失(lost wakeup)的经典模式

std::atomic::notify_one 和 notify_all 不缓存通知,若 notify 发生在 wait 之前,该次通知即被丢弃;因此必须保证“状态更新 → 通知”发生在“检查状态 → 等待”逻辑之后,通常需循环检查加等待。

C++14
C++14

C++14 对 C++11 的修正与增强版本,适合旧系统维护和较老工具链兼容。

下载

1、等待线程必须使用 do-while 或 while 循环包裹 wait,例如:while (flag.load(std::memory_order_acquire) == 0) { flag.wait(expected); }

2、每次 wait 返回后,立即重新 load 当前值并验证条件是否真正满足,不可假设唤醒即代表条件成立

3、通知线程应在修改所有相关共享数据后,再执行 store + notify,且 store 与 notify 之间不得插入可能被重排的非原子操作

四、防止虚假唤醒外的数据竞争

即使 wait 成功返回,若所反映的状态背后关联非原子数据(如结构体字段),而写线程未施加恰当内存序约束,读线程仍可能看到部分更新的撕裂状态。

1、若原子变量 flag 表示“struct Data d 已就绪”,则写线程必须在 d 的所有字段赋值完成后,再以 memory_order_release 存储 flag

2、读线程在 flag.wait() 返回后,必须以 memory_order_acquire 加载 flag,再访问 d 的字段

3、禁止仅用 std::atomic 作为复合对象就绪标志而不约束其前后非原子内存操作的顺序

五、适配不同平台的底层等待原语

std::atomic::wait 在 Linux 依赖 futex,在 Windows 依赖 WaitOnAddress,在 macOS(截至 C++20 实现)可能回退至 mutex+condvar 模拟;若目标平台不支持原生等待,行为将降级,影响性能与语义。

1、编译时检查 __cpp_lib_atomic_wait 是否定义,确认标准库支持该特性

2、Linux 环境下通过 strace -e trace=futex 验证程序是否实际触发 futex 系统调用

3、macOS 用户应避免在性能关键路径依赖 wait/notify,需查阅所用 libc++ 版本是否已启用 WaitOnAddress 替代方案

热门AI工具

更多
讯飞绘文

讯飞绘文是一款由科大讯飞推出的一站式 AIGC 内容运营平台。

豆包大模型

豆包大模型是一款由字节跳动推出的企业级大语言模型服务平台。

UpDream
UpDream Hot

一款AI视频创作工具,主要用于哔哩哔哩推出的自研AI视频创作工具,适合需要提升相关任务效率的用户。

WorkBuddy

一款AI办公效率工具,主要用于腾讯云推出的AI原生桌面智能体工作台,适合需要提升相关任务效率的用户。

火山引擎

火山引擎是一款面向企业的云计算与AI服务平台。

超级简历WonderCV

一款AI办公效率工具,主要用于免费求职简历模版下载制作,应届生职场人必备简历制作神器,适合需要提升相关任务效率的用户。

Laper
Laper Hot

Laper是专为编剧、导演和制片人推出的 AI 原生剧本创作工具。

DeepSeek

DeepSeek是一款面向对话、写作、编程和推理场景的AI大模型工具。

立刻MV
立刻MV Hot

立刻MV是一款AI文本写作工具,AI 音乐视频(MV)创作工具。

相关专题

更多
C语言变量命名
C语言变量命名

c语言变量名规则是:1、变量名以英文字母开头;2、变量名中的字母是区分大小写的;3、变量名不能是关键字;4、变量名中不能包含空格、标点符号和类型说明符。php中文网还提供c语言变量的相关下载、相关课程等内容,供大家免费下载使用。

3469

2023.06.20

c语言入门自学零基础
c语言入门自学零基础

C语言是当代人学习及生活中的必备基础知识,应用十分广泛,本专题为大家c语言入门自学零基础的相关文章,以及相关课程,感兴趣的朋友千万不要错过了。

2408

2023.07.25

c语言运算符的优先级顺序
c语言运算符的优先级顺序

c语言运算符的优先级顺序是括号运算符 > 一元运算符 > 算术运算符 > 移位运算符 > 关系运算符 > 位运算符 > 逻辑运算符 > 赋值运算符 > 逗号运算符。本专题为大家提供c语言运算符相关的各种文章、以及下载和课程。

1340

2023.08.02

c语言数据结构
c语言数据结构

数据结构是指将数据按照一定的方式组织和存储的方法。它是计算机科学中的重要概念,用来描述和解决实际问题中的数据组织和处理问题。数据结构可以分为线性结构和非线性结构。线性结构包括数组、链表、堆栈和队列等,而非线性结构包括树和图等。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

1278

2023.08.09

c语言random函数用法
c语言random函数用法

c语言random函数用法:1、random.random,随机生成(0,1)之间的浮点数;2、random.randint,随机生成在范围之内的整数,两个参数分别表示上限和下限;3、random.randrange,在指定范围内,按指定基数递增的集合中获得一个随机数;4、random.choice,从序列中随机抽选一个数;5、random.shuffle,随机排序。

1396

2023.09.05

c语言const用法
c语言const用法

const是关键字,可以用于声明常量、函数参数中的const修饰符、const修饰函数返回值、const修饰指针。详细介绍:1、声明常量,const关键字可用于声明常量,常量的值在程序运行期间不可修改,常量可以是基本数据类型,如整数、浮点数、字符等,也可是自定义的数据类型;2、函数参数中的const修饰符,const关键字可用于函数的参数中,表示该参数在函数内部不可修改等等。

2298

2023.09.20

c语言get函数的用法
c语言get函数的用法

get函数是一个用于从输入流中获取字符的函数。可以从键盘、文件或其他输入设备中读取字符,并将其存储在指定的变量中。本文介绍了get函数的用法以及一些相关的注意事项。希望这篇文章能够帮助你更好地理解和使用get函数 。

3740

2023.09.20

c数组初始化的方法
c数组初始化的方法

c语言数组初始化的方法有直接赋值法、不完全初始化法、省略数组长度法和二维数组初始化法。详细介绍:1、直接赋值法,这种方法可以直接将数组的值进行初始化;2、不完全初始化法,。这种方法可以在一定程度上节省内存空间;3、省略数组长度法,这种方法可以让编译器自动计算数组的长度;4、二维数组初始化法等等。

17475

2023.09.22

Vite 项目如何打包和部署
Vite 项目如何打包和部署

Vite项目打包部署专题汇集生产构建、产物预览、输出目录、资源路径、Nginx与GitHub Pages部署及常见白屏和路由404问题的已审核文章,帮助读者完成上线流程。

20

2026.10.28

热门下载

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

精品课程

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

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn