news 2026/7/3 21:18:56

C++内存序

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
C++内存序

在 C++ 中,内存序(Memory Order)是多线程编程中原子操作的重要概念,它用于控制原子操作的内存同步行为。C++11 引入了<atomic>头文件,提供了内存序来控制多线程环境下的内存访问顺序。

内存序的作用

内存序主要解决两个问题:

  1. 可见性:一个线程对共享数据的修改何时对其他线程可见

  2. 顺序性:操作指令的执行顺序如何被其他线程观察

六种内存序

1.memory_order_relaxed

最宽松的顺序约束,只保证原子性,不保证顺序。

cpp

std::atomic<int> x(0); x.store(1, std::memory_order_relaxed); // 不保证其他线程立即看到这个值

2.memory_order_consume

依赖于该原子操作的后续操作不会被重排序到该操作之前(依赖关系)。

cpp

std::atomic<int*> ptr; int data; // 线程1 data = 42; ptr.store(&data, std::memory_order_consume); // 线程2 int* p = ptr.load(std::memory_order_consume); if (p != nullptr) { // 保证能看到 data = 42 int val = *p; }

3.memory_order_acquire

用于读操作,保证该操作之后的所有读写不会被重排序到该操作之前。

cpp

std::atomic<bool> flag(false); int data = 0; // 线程1 data = 42; flag.store(true, std::memory_order_release); // 线程2 while (!flag.load(std::memory_order_acquire)); // 这里保证能看到 data = 42

4.memory_order_release

用于写操作,保证该操作之前的所有读写不会被重排序到该操作之后。

cpp

// 与上面 acquire 配合使用

5.memory_order_acq_rel

同时包含 acquire 和 release 语义,用于读-修改-写操作。

cpp

std::atomic<int> counter(0); counter.fetch_add(1, std::memory_order_acq_rel);

6.memory_order_seq_cst

最严格的顺序约束(默认),保证所有线程看到相同的操作顺序。

cpp

std::atomic<int> x(0); x.store(1); // 默认使用 memory_order_seq_cst

典型使用模式

1.Release-Acquire 同步

cpp

std::atomic<bool> ready(false); int data = 0; // 线程1(生产者) data = 42; ready.store(true, std::memory_order_release); // 线程2(消费者) while (!ready.load(std::memory_order_acquire)); // 这里保证能看到 data = 42

2.Release-Consume 同步

cpp

std::atomic<int*> ptr(nullptr); int value; // 线程1 value = 100; ptr.store(&value, std::memory_order_release); // 线程2 int* p = ptr.load(std::memory_order_consume); if (p != nullptr) { // 保证能看到 p 指向的数据 int v = *p; // v = 100 }

3.自旋锁实现

cpp

class SpinLock { std::atomic_flag flag = ATOMIC_FLAG_INIT; public: void lock() { while (flag.test_and_set(std::memory_order_acquire)); } void unlock() { flag.clear(std::memory_order_release); } };

性能考虑

  • relaxed:性能最好,但需要谨慎使用

  • seq_cst:性能最差,但最容易理解

  • acquire/release:在性能和正确性之间取得平衡

实用建议

  1. 优先使用默认的 seq_cst,除非有性能瓶颈

  2. 理解 happens-before 关系后再使用宽松内存序

  3. 测试多线程代码,内存序错误很难调试

  4. 使用现成的同步原语(如 mutex, condition_variable)通常更安全

示例:无锁计数器

cpp

#include <atomic> #include <thread> #include <iostream> class Counter { std::atomic<int> count{0}; public: void increment() { count.fetch_add(1, std::memory_order_relaxed); } int get() const { return count.load(std::memory_order_acquire); } }; int main() { Counter counter; std::thread t1([&]() { for (int i = 0; i < 1000000; ++i) { counter.increment(); } }); std::thread t2([&]() { for (int i = 0; i < 1000000; ++i) { counter.increment(); } }); t1.join(); t2.join(); std::cout << "Count: " << counter.get() << std::endl; return 0; }
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/28 22:57:33

基于纳什博弈的多微网主体电热双层共享策略Matlab代码

✅作者简介&#xff1a;热爱科研的Matlab仿真开发者&#xff0c;擅长数据处理、建模仿真、程序设计、完整代码获取、论文复现及科研仿真。 &#x1f34e; 往期回顾关注个人主页&#xff1a;Matlab科研工作室 &#x1f447; 关注我领取海量matlab电子书和数学建模资料 &#x1…

作者头像 李华
网站建设 2026/7/2 1:51:42

Microsoft 开发的关系型数据库管理系统(RDBMS)

SQL Server 简介 SQL Server 是由 Microsoft 开发的关系型数据库管理系统&#xff08;RDBMS&#xff09;&#xff0c;支持企业级数据管理、分析和应用开发。其核心功能包括数据存储、事务处理、商业智能&#xff08;BI&#xff09;和高可用性解决方案。 SQL Server 版本 企业…

作者头像 李华
网站建设 2026/7/2 9:00:04

计算机深度学习毕设实战-基于人工智能深度学习的猫的种类识别基于python-cnn深度学习的猫的种类识别

博主介绍&#xff1a;✌️码农一枚 &#xff0c;专注于大学生项目实战开发、讲解和毕业&#x1f6a2;文撰写修改等。全栈领域优质创作者&#xff0c;博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围&#xff1a;&am…

作者头像 李华
网站建设 2026/6/26 8:48:41

售后完善的高速线剥线机源头厂家

《高速线剥线机哪家好&#xff1a;专业深度测评》开篇&#xff1a;定下基调在工业自动化与智能制造快速发展的今天&#xff0c;高速线剥线机作为电线电缆加工环节中的关键设备&#xff0c;其效率、精度与稳定性直接影响生产节奏与产品质量。面对市场上琳琅满目的品牌与型号&…

作者头像 李华
网站建设 2026/6/25 14:50:43

从入门到精通:程序员必学的9种RAG架构实战指南,解决大模型幻觉问题

本文详细介绍了9种RAG架构及其适用场景&#xff0c;包括标准RAG、对话式RAG、纠正性RAG等&#xff0c;强调应根据实际需求选择合适架构而非盲目追求复杂度。文章提供了从简单开始的决策框架&#xff0c;提醒避免过度设计、忽略检索质量等陷阱。RAG可将语言模型从"自信的谎…

作者头像 李华