C++怎么使用原子操作实现线程安全

来源:IT编程作者:韦伯头衔:草根站长
导读:本期聚焦于小伙伴创作的《C++怎么使用原子操作实现线程安全》,敬请观看详情,探索知识的价值。以下视频、文章将为您系统阐述其核心内容与价值。如果您觉得《C++怎么使用原子操作实现线程安全》有用,将其分享出去将是对创作者最好的鼓励。

在多线程编程中,多个线程同时读写同一个共享变量时,很容易出现数据竞争问题,导致程序出现不可预期的运行结果。C++11标准引入的atomic模板类提供了原子操作支持,可以在无锁的情况下保证共享变量的线程安全,是多线程开发中常用的工具。

C++怎么使用原子操作实现线程安全

atomic基础概念

原子操作指的是不可被中断的一个或一组操作,执行过程中不会被其他线程的操作干扰。C++的atomic模板可以包装任意可平凡复制的类型,被包装后的变量所有读写操作都是原子的,不需要额外的同步措施。

和互斥锁相比,原子操作的性能开销更小,适合轻量级的共享变量同步场景,但无法处理复杂的临界区逻辑。

atomic基本用法

定义原子变量

使用std::atomic定义原子变量时,需要包含<atomic>头文件,基本定义方式如下:

#include <atomic>
#include <iostream>

// 定义原子int类型变量,初始值为0
std::atomic<int> counter(0);
// 定义原子bool类型变量
std::atomic<bool> flag(false);

常用原子操作

atomic提供了多种原子操作接口,常用的包括读写、自增自减、交换等:

  • store:原子写操作,将值写入原子变量
  • load:原子读操作,读取原子变量的当前值
  • fetch_add:原子加操作,返回加之前的值
  • fetch_sub:原子减操作,返回减之前的值
  • exchange:原子交换操作,将新值写入原子变量并返回旧值
  • compare_exchange_strong:原子比较交换操作,若当前值等于期望值则替换为新值

实战示例:多线程计数器

下面通过一个多线程计数器的示例,展示原子操作的实际使用效果。如果不使用原子操作,多个线程同时修改同一个计数器会出现计数丢失的问题。

#include <atomic>
#include <iostream>
#include <thread>
#include <vector>

// 定义原子计数器,初始值为0
std::atomic<int> global_counter(0);

// 每个线程执行的函数,对计数器加1000次
void increment_task() {
    for (int i = 0; i < 1000; i++) {
        // 原子自增操作,等价于global_counter++,但保证线程安全
        global_counter.fetch_add(1, std::memory_order_relaxed);
    }
}

int main() {
    std::vector<std::thread> threads;
    // 创建10个线程
    for (int i = 0; i < 10; i++) {
        threads.emplace_back(increment_task);
    }
    // 等待所有线程执行完成
    for (auto& t : threads) {
        t.join();
    }
    // 输出最终计数器的值,预期为10*1000=10000
    std::cout << "最终计数器值: " << global_counter.load() << std::endl;
    return 0;
}

上述代码中,10个线程每个对计数器加1000次,使用原子操作后最终输出结果一定是10000,不会出现计数丢失的情况。如果去掉原子操作,改用普通int变量,最终结果通常会小于10000。

内存顺序说明

原子操作的接口通常可以指定内存顺序参数,用于控制操作的同步和排序效果,常用的内存顺序有:

内存顺序说明
std::memory_order_relaxed宽松内存顺序,只保证操作原子性,不保证同步和排序,性能最高
std::memory_order_acquire获取操作,当前线程后续的所有读写操作都不能重排到该操作之前
std::memory_order_release释放操作,当前线程之前的所有读写操作都不能重排到该操作之后
std::memory_order_seq_cst顺序一致性内存顺序,默认选项,保证所有线程看到的操作顺序一致,开销最大

对于简单的计数器场景,使用std::memory_order_relaxed就足够,不需要更强的内存顺序保证,这样可以获得更好的性能。

使用注意事项

  • 只有atomic包装的变量的操作才是原子的,对原子变量的普通读写操作如果没有通过原子接口调用,仍然可能不是原子的
  • 原子操作只保证单个变量的操作原子性,无法处理多个变量组合的临界区逻辑,这种场景还是需要互斥锁
  • 不是所有类型都可以作为atomic的模板参数,模板参数类型需要满足可平凡复制的要求
  • 原子变量的初始化不能使用普通赋值,需要在构造时初始化,或者使用store接口赋值
原子操作是C++多线程编程中高效的同步手段,合理使用可以大幅提升程序性能,开发者需要根据实际场景选择合适的原子操作和内存顺序,避免过度使用或者错误使用。

C++atomic线程安全原子操作修改时间:2026-06-30 07:24:25

免责声明:​ 已尽一切努力确保本网站所含信息的准确性。网站内容多为原创整理与精心编撰,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们处理。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。