0

0

C++如何使用std::atomic实现无锁编程?(原子操作)

冰火之心

冰火之心

发布时间:2026-01-06 17:55:02

|

736人浏览过

|

来源于php中文网

原创

std::atomic 是 C++11 提供的无锁原子操作工具,支持 load/store/exchange/compare_exchange 等操作,需合理选用 memory_order 并注意 lock-free 性、ABA 问题及正确性验证。

c++如何使用std::atomic实现无锁编程?(原子操作)

std::atomic 是 C++11 引入的核心工具,用于在多线程环境中安全地读写共享变量,无需互斥锁(mutex),从而实现无锁(lock-free)编程。它的关键在于:所有操作都是原子的,不会被线程调度打断,且编译器和 CPU 会按需插入内存屏障,防止重排序导致的数据竞争。

基础用法:声明与基本操作

std::atomic 封装一个类型为 T 的变量(T 需为 trivially copyable,如 int、bool、指针等)。常用操作包括 load()、store()、exchange() 和 compare_exchange_weak()/strong():

  • load():原子读,等价于 operator T(),默认 memory_order_seq_cst(最强顺序)
  • store(val):原子写,等价于 operator=(val)
  • exchange(val):原子地将原值替换为 val,并返回旧值
  • compare_exchange_weak(expected, desired):若当前值等于 expected,则设为 desired 并返回 true;否则将当前值写入 expected 并返回 false(可能伪失败,需循环重试)

实现无锁计数器(典型例子)

下面是一个线程安全的无锁自增计数器,不依赖 mutex:

std::atomic counter{0};

void increment() { counter.fetch_add(1, std::memory_order_relaxed); }

int get_value() { return counter.load(std::memory_order_acquire); }

这里用 fetch_add 替代 read-modify-write 手动实现,避免竞态。注意:memory_order_relaxed 适用于仅需原子性、不依赖其他内存操作顺序的场景(如计数器);若需同步其他数据,应升级为 acquire/release 或保持默认 seq_cst

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

动感购物HTML
动感购物HTML

修正了V1.10的一些BUG感购物HTML系统是集合目前网络所有购物系统为参考而开发,代码采用DIV编号,不管从速度还是安全我们都努力做到最好,此版虽为免费版但是功能齐全,无任何错误,特点有:专业的、全面的电子商务解决方案,使您可以轻松实现网上销售;自助式开放性的数据平台,为您提供充满个性化的设计空间;功能全面、操作简单的远程管理系统,让您在家中也可实现正常销售管理;严谨实用的全新商品数据库,便于

下载

实现无锁(push/pop)

无锁栈依赖 compare_exchange_weak 实现 ABA 问题规避(通常配合 tag pointer 或 hazard pointer,简单版可先忽略 ABA):

struct Node {
    int data;
    Node* next;
};

std::atomic head{nullptr};

void push(int data) { Node* node = new Node{data, nullptr}; node->next = head.load(std::memory_order_relaxed); while (!head.compare_exchange_weak(node->next, node, std::memory_order_release, std::memory_order_relaxed)) { // 若 head 已变,node->next 被自动更新为当前 head,继续重试 } }

pop 类似,但需小心处理内存释放(建议搭配 std::shared_ptr 或专用内存回收机制,否则易出现 use-after-free)。

注意事项与常见陷阱

无锁 ≠ 无脑高效。实际使用中要注意:

  • 不是所有 std::atomic 都是 lock-free:可用 is_lock_free() 检查,例如某些平台下 atomic 可能回退到内部锁
  • 过度依赖 seq_cst 会显著降低性能;应根据同步需求选择合适 memory_order(如 producer-consumer 场景常用 release/acquire)
  • compare_exchange_weak 可能因硬件原因“假失败”,必须放在 do-while 或 while 循环中重试;strong 版本不假失败但可能更慢
  • 无锁结构的正确性极难验证,建议优先使用成熟库(如 folly::AtomicSharedPtr、boost::lockfree)或标准容器(std::queue 不是无锁的,勿误用)

相关专题

更多
while的用法
while的用法

while的用法是“while 条件: 代码块”,条件是一个表达式,当条件为真时,执行代码块,然后再次判断条件是否为真,如果为真则继续执行代码块,直到条件为假为止。本专题为大家提供while相关的文章、下载、课程内容,供大家免费下载体验。

83

2023.09.25

string转int
string转int

在编程中,我们经常会遇到需要将字符串(str)转换为整数(int)的情况。这可能是因为我们需要对字符串进行数值计算,或者需要将用户输入的字符串转换为整数进行处理。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

314

2023.08.02

int占多少字节
int占多少字节

int占4个字节,意味着一个int变量可以存储范围在-2,147,483,648到2,147,483,647之间的整数值,在某些情况下也可能是2个字节或8个字节,int是一种常用的数据类型,用于表示整数,需要根据具体情况选择合适的数据类型,以确保程序的正确性和性能。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

528

2024.08.29

c++怎么把double转成int
c++怎么把double转成int

本专题整合了 c++ double相关教程,阅读专题下面的文章了解更多详细内容。

49

2025.08.29

C++中int的含义
C++中int的含义

本专题整合了C++中int相关内容,阅读专题下面的文章了解更多详细内容。

193

2025.08.29

c++怎么把double转成int
c++怎么把double转成int

本专题整合了 c++ double相关教程,阅读专题下面的文章了解更多详细内容。

49

2025.08.29

C++中int、float和double的区别
C++中int、float和double的区别

本专题整合了c++中int和double的区别,阅读专题下面的文章了解更多详细内容。

97

2025.10.23

堆和栈的区别
堆和栈的区别

堆和栈的区别:1、内存分配方式不同;2、大小不同;3、数据访问方式不同;4、数据的生命周期。本专题为大家提供堆和栈的区别的相关的文章、下载、课程内容,供大家免费下载体验。

380

2023.07.18

PPT动态图表制作教程大全
PPT动态图表制作教程大全

本专题整合了PPT动态图表制作相关教程,阅读专题下面的文章了解更多详细内容。

13

2026.01.07

热门下载

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

相关下载

更多

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
HTML5/CSS3/JavaScript/ES6入门课程
HTML5/CSS3/JavaScript/ES6入门课程

共102课时 | 6.6万人学习

前端基础到实战(HTML5+CSS3+ES6+NPM)
前端基础到实战(HTML5+CSS3+ES6+NPM)

共162课时 | 18.6万人学习

第二十二期_前端开发
第二十二期_前端开发

共119课时 | 12.2万人学习

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

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