C++ 并行编程之memory_order
一.如果只是简单地解决在多线程中对共享资源的读写并发问题,只需要用C++以下内容: 线程类 thread, 原子数据类模板 atomic<T> t, 互斥 mutex, 锁 lock, 条件变量 condition_variables.
二.在此基础上,如果想在并行编程中获得更好的性能,尤其当使用的是一些弱内存顺序的平台(比如PowerPC)的话,设定原子操作间的内存顺序则很有必要.
C++11 加入了支持并行编程的原子操作模块,而所有的原子操作都有一个参数 memory_order.
1.内存模型 简介
内存模型是一个硬件上的概念,表示机器指令是以什么样的顺序被处理器执行的 (现代的处理器不是逐条处理机器指令的) .
#include <thread> #include <atomic> atomic<int> a; atomic<int> b; void threadHandle() { int t = 1; a = t; b = 2; // b 的赋值不依赖 a }
在上面的线程处理函数中的三行代码,在寄存器中实际执行顺序可能与代码写的顺序不一致.在不同的机器平台下,处理器有可能对指令周期的执行顺序优化(一个时钟周期发射多条指令),就是说它可能让 b 的赋值语句比 a 的赋值语句先执行.
此时,如果有一个线程在循环地打印 a 和 b 的值,那么结果并不总是 a == 1 和 b == 2.
2.如何保证指令执行顺序
保证执行顺序会牺牲一些执行效率,因为这意味着放弃了编译器、处理器等的优化处理。
强顺序的内存模型指: 代码顺序和寄存器实际执行的顺序一致
弱顺序的内存模型指: 寄存器实际执行的顺序与代码顺序不一致,被处理器调整过
3.C++ 并行编程: 设定 指令执行顺序
typedef enum memory_order { memory_order_relaxed, // 不对执行顺序做保证 memory_order_acquire, // 本线程中,所有后续的读操作必须在本条原子操作完成后执行 memory_order_release, // 本线程中,所有之前的写操作完成后才能执行本条原子操作 memory_order_acq_rel, // 同时包含 memory_order_acquire 和 memory_order_release memory_order_consume, // 本线程中,所有后续的有关本原子类型的操作,必须在本条原子操作完成之后执行 memory_order_seq_cst // 全部存取都按顺序执行 } memory_order;
测试: 下面的代码可能会打印出 a == 0; b == 2 这样的结果
1 #include <iostream> 2 #include <thread> 3 #include <atomic> 4 5 atomic<int> a{ 0 }; 6 atomic<int> b{ 0 }; 7 void SetValue() 8 {// atomic类模板中的函数都是原子操作. int temp = a.load();相当于 int temp = a的原子操作 9 int t = 1; 10 a.store(t, memory_order_relaxed); // 相当于 a = t的原子操作 11 b.store(2, memory_order_relaxed); // 相当于 b = 2的原子操作 12 } 13 void Observer() 14 { 15 cout << a << b << endl; 16 } 17 18 int main() 19 { 20 thread T1(SetValue,0); 21 thread T2(Observer, 0); 22 23 T1.join(); // 主线程(调用方)等待子线程 T1 执行完成,才能继续执行,阻塞 24 T2.join(); // 同上,执行这一行前: T1已经结束,T2很可能也结束了 25 26 return 0; 27 }
参考:C++ 多线程与内存模型资料汇
memory order相关问题
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 25岁的心里话