std::atomic 不能直接实现无锁队列,因其仅保证单变量原子性,而队列操作需多位置协同更新且面临 ABA 问题;真正无锁需 CAS 循环+内存序控制,SPSC 场景可用 std::atomic + compare_exchange_weak 安全实现,MPMC 则必须引入版本号防 ABA。
因为 std::atomic 只保证单个变量的原子读写,而队列操作(如入队/出队)需要**多个内存位置协同更新**(比如同时修改 head、tail 和节点数据),仅靠单个 std::atomic 无法避免 ABA 问题或中间态不一致。真正无锁(lock-free)队列必须基于 CAS(Compare-And-Swap)循环重试 + 内存序控制,且通常需自定义节点结构和指针管理。
SPSC 是唯一能用纯 std::atomic + compare_exchange_weak 安全实现的常见场景。关键点:
head 和 tail 必须是 std::atomic,且初始化为同一哨兵节点tail 执行 CAS:期望值为当前 tail,新值为新节点;失败则重试head 执行 CAS:期望值为当前 head,新值为 head->next
memory_order_acquire(读)和 memory_order_release(写)防止指令重排delete 节点——SPSC 下可复用内存池,否则需配合 hazard pointer 或 RCU
struct Node {
int data;
Node* next;
};
class SPSCQueue {
std::atomic> head_;
std::atomic> tail_;
// ... 构造函数中分配哨兵节点
public:
bool tryenqueue(int val) {
Node node = new Node{val, nullptr};
Node tail = tail.load(std::memory_orderacquire);
while (!tail.compare_exchange_weak(tail, node, std::memory_order_acq_rel)) {
// CAS 失败,说明 tail 已被其他线程推进,继续重试
}
tail->next = node; // 此时 tail 仍是旧 tail,安全写入
return true;
}
};
无锁 ≠ 无竞争,而是指“至少有一个线程能在有限步内完成操作”。所以所有 CAS 循环必须:
sleep、yield 或任何阻塞系统调用volatile 或 std::atomic_thread_fence 防止寄存器缓存导致无限重试当一个节点被出队、释放、再重新入队时,head 指针可能回到相同地址,但内容已变
。此时单纯比较指针值的 CAS 会误判成功。解决方案:
std::atomic 包装指针 + 版本号(低位存计数,高位存指针),即「tagged pointer」std::atomic<:pair size_t>>(C++20 起支持原子 pair)moodycamel::ConcurrentQueue 就采用带版本号的指针 CASstd::shared_ptr 替代——引用计数本身不是无锁的,其内部仍用锁真正可靠的 MPMC 无锁队列极少手写,建议优先集成经过充分测试的第三方实现。自己实现时,最容易被忽略的是内存序组合与 ABA 防御的耦合性——改错一个 memory_order 参数,就可能导致偶发崩溃或数据丢失。
# node
# ai
# c++
# 数据丢失
# 无锁
# 为什么
# red
# volatile
# 循环
# 指针
# 线程
# pointer
# delete
# 并发
# bug
# 值为
# 重试
# 的是
# 这是
# 多个
# 是指
# 已被
# 能在
# 仍是
# 自定义
相关栏目:
【
Google疑问12 】
【
Facebook疑问10 】
【
网络优化76771 】
【
技术知识130152 】
【
IDC云计算60162 】
【
营销推广131313 】
【
AI优化88182 】
【
百度推广37138 】
【
网站推荐60173 】
【
精选阅读31334 】
相关推荐:
Win11怎么关闭定位服务_保护Win11位置隐私设置指南【详解】
Win11如何更新显卡驱动 Win11检查和安装设备驱动程序【方法】
Win11怎么设置虚拟内存最佳大小_Windows11性能选项自定义分页文件
php删除数据怎么软删除_添加is_del字段标记删除【技巧】
php中::能访问全局变量吗_全局作用域与类作用域区分【操作】
Win11怎么关闭自动维护 Win11禁用系统自动维护功能【优化】
Win11怎么更改管理员名字 Win11修改账户名称详细步骤【教程】
Win11怎么开启HDR模式_Windows 11高动态范围显示设置指南【详解】
Win10如何备份驱动程序_Win10驱动备份步骤【攻略】
Python字符串处理进阶_切片方法解析【指导】
Win10任务栏天气和资讯怎么关闭 Win10禁用新闻和兴趣功能【教程】
如何在Golang中实现微服务负载均衡_Golang负载均衡策略与实现示例
Windows10系统怎么查看运行时间_Win10 CPU正常运行时间查询
Win11怎么更改任务栏位置_修改注册表将Win11任务栏置顶【教程】
Python文件和流处理指南_高效读写大体积数据文件
Python面向对象实战讲解_类与设计模式深入理解
Win10怎么关闭自动更新错误重启 Win10策略禁止失败补丁强制重启【防护】
手机php文件怎么变成mp4_安卓苹果打开php转mp4方法【教程】
Windows10如何更改开机密码_Win10登录选项更改密码教程
Mac自带的词典App怎么用_Mac添加和使用多语言词典【技巧】
Windows10怎么用“讲述人”读屏辅助 Windows10轻松使用开启讲述人朗读屏幕文字帮助视障用户【教程】
Win11怎么设置右键刷新选项_Windows11显示更多选项技巧
Python数据挖掘进阶教程_分类回归与聚类案例解析
c++的位运算怎么用 与、或、异或、移位操作详解【底层知识】
如何在Golang中实现RPC异步返回_Golang RPC异步处理与回调方法
Windows10电脑怎么查看硬盘通电时间_Win10使用工具检测磁盘健康
Python多进程教程_multiprocessing模块实战
Windows笔记本无法进入睡眠模式怎么办?(电源疑难解答)
Python大文件处理策略_内存优化说明【指导】
php8.4xdebug无法调试怎么办_php8.4xdebug配置问题解决【解答】
LINUX怎么进行文本内容搜索_Linux grep命令正则表达式用法大全【教程】
Go 中实现 Python urllib.quote() 等效功能的正确方式
win11 OneDrive怎么彻底关闭 Win11禁用并卸载OneDrive教程【分享】
Python对象比较与排序_魔术方法解析【教程】
php8.4如何实现队列任务_php8.4redis队列简单实现方法【教程】
Win11如何设置开机自动联网 Win11宽带连接自动拨号【步骤】
c# 如何深拷贝和浅拷贝
如何在Golang中验证模块完整性_Golanggo.sum校验与安全实践
Windows10系统怎么查看CPU核心数_Win10逻辑处理器数量查看
Windows10任务栏图标变成白色文件_Win10重建图标缓存修复方法
GML (Geography Markup Language)是什么,它如何用XML来表示地理空间信息?
Win11怎么设置声音输出设备_Windows11音量合成器单独调节应用
MAC怎么一键隐藏桌面所有图标_MAC极简模式切换与终端指令【方法】
MySQL 中使用 IF 和 CASE 实现查询字段条件化显示
C++友元类使用场景_C++类间协作设计方式讲解
Win11怎么设置默认PDF阅读器 Win11修改PDF打开方式【步骤】
Windows10无法识别USB设备描述符请求失败_通用串行总线控制器修复
Win11麦克风没声音怎么设置_Win11麦克风权限及驱动修复【教程】
如何在 Go 中创建包含映射(map)的切片(slice)结构
Win11如何卸载OneDrive_Win11卸载OneDrive方法【教程】
2026-01-02
致胜网络推广营销网专注海外推广十年,是谷歌推广.Facebook广告全球合作伙伴,我们精英化的技术团队为企业提供谷歌海外推广+外贸网站建设+网站维护运营+Google SEO优化+社交营销为您提供一站式海外营销服务。