图解Modern Cpp内存序

文章目录

      • 为什么需要内存序?
      • 内存序的分类
      • 内存序的作用
        • 指令重排序限制
        • 跨线程可见性
    • 样例分析
      • 完全乱序: `memory_order_relaxed`
      • 读写同步: `memory_order_acquire` 和 `memory_order_release`
      • 一致性 `memory_order_seq_cst`
      • 6. 内存序的权衡
      • 总结

C++ 内存序(Memory Order)定义了多线程环境下对共享内存的操作顺序和可见性规则. 它是 C++ 原子操作(std::atomic)的重要组成部分, 允许开发者在性能和线程安全之间进行权衡.


为什么需要内存序?

在多线程编程中, 现代 CPU 和编译器会进行指令重排序, 以优化性能. 指令重排序可能导致线程间的操作顺序与程序逻辑不一致, 从而引发数据竞争. C++ 的内存序通过提供一组规则, 确保线程间操作的正确性, 同时尽量减少性能损失.


内存序的分类

C++ 提供了六种内存序, 分别针对不同的同步需求和性能优化:

内存序描述使用场景
memory_order_relaxed不保证操作的顺序, 仅保证原子性性能优先, 不需要顺序约束
memory_order_consume对数据依赖操作可见(目前等价于 acquire)数据依赖同步(罕见使用)
memory_order_acquire确保当前操作之前的读取有效, 阻止后续操作重排到前面多线程读取, 确保前置可见性
memory_order_release确保当前操作之后的写入有效, 阻止前序操作重排到后面多线程写入, 确保后置可见性
memory_order_acq_rel同时具备 acquirerelease 的效果读写同步
memory_order_seq_cst全局顺序一致性, 最严格的模式默认模式, 简单但性能最低

内存序的作用

指令重排序限制
  • relaxed: 允许指令完全重排序.
  • acquire: 禁止读取操作重排到当前操作之前.
  • release: 禁止写入操作重排到当前操作之后.
  • seq_cst: 严格禁止所有重排序.
跨线程可见性
  • acquire: 确保当前线程可以看到其他线程释放的内存操作.
  • release: 确保当前线程的操作对其他线程可见.

样例分析

完全乱序: memory_order_relaxed

允许线程独立执行, 不保证顺序或可见性, 仅保证操作原子性.

#include <atomic>
#include <iostream>
#include <thread>int main() {std::atomic<int> x(1);std::atomic<int> y(2);std::jthread t1([&]() {y.store(4, std::memory_order_relaxed);x.store(3, std::memory_order_relaxed);});std::jthread t2([&]() {std::cout << x.load(std::memory_order_relaxed) << std::endl;std::cout << y.load(std::memory_order_relaxed) << std::endl;});return 0;
}

可能有如下 4 种输出:

xy可能的执行顺序
12c1
32c2
14在这里插入图片描述
34在这里插入图片描述

读写同步: memory_order_acquirememory_order_release

用于线程间同步, 确保操作的可见性和顺序.

#include <atomic>
#include <iostream>
#include <thread>int main() {std::atomic<int> x(0);std::atomic<int> y(0);std::jthread t1([&]() {y.store(2, std::memory_order_release);x.store(1, std::memory_order_release);});std::jthread t2([&]() {std::cout << x.load(std::memory_order_acquire) << std::endl;std::cout << y.load(std::memory_order_acquire) << std::endl;});return 0;
}

可能的执行结果:

xy可能的执行顺序
12ra_c1
14ra_c2
34ra_c3

一致性 memory_order_seq_cst

最严格的内存序, 确保全局顺序一致性.

#include <atomic>
#include <thread>
#include <iostream>std::atomic<int> x(0), y(0);void thread1() {x.store(1, std::memory_order_seq_cst);std::cout << "y: " << y.load(std::memory_order_seq_cst) << std::endl;
}void thread2() {y.store(1, std::memory_order_seq_cst);std::cout << "x: " << x.load(std::memory_order_seq_cst) << std::endl;
}int main() {std::thread t1(thread1), t2(thread2);t1.join();t2.join();return 0;
}

可能的执行步骤

xy可能的执行顺序
34sc_c1
32sc_c2

结果: 输出顺序严格受控, 但性能最低.


6. 内存序的权衡

  • 性能优先: relaxed 内存序提供最高性能, 但不保证顺序和可见性.
  • 正确性优先: acquire/release 是实际编程中常用的同步机制.
  • 简单实现: seq_cst 是默认选择, 但代价是性能下降.

总结

  • C++ 内存序是原子操作的关键组成部分, 用于平衡性能和同步需求.
  • 默认使用 memory_order_seq_cst, 在性能敏感场景中使用 relaxedacquire/release.
  • 结合实际多线程需求合理选择内存序, 有助于写出高效且安全的代码.

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/497444.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

MySQL第二弹----CRUD

笔上得来终觉浅,绝知此事要躬行 &#x1f525; 个人主页&#xff1a;星云爱编程 &#x1f525; 所属专栏&#xff1a;MySQL &#x1f337;追光的人&#xff0c;终会万丈光芒 &#x1f389;欢迎大家点赞&#x1f44d;评论&#x1f4dd;收藏⭐文章 ​ 一、修改表 使用ALTER …

Pytorch | 利用SMI-FGRM针对CIFAR10上的ResNet分类器进行对抗攻击

Pytorch | 利用I-FGSSM针对CIFAR10上的ResNet分类器进行对抗攻击 CIFAR数据集SMI-FGRM介绍SMI-FGRM算法流程 SMI-FGRM代码实现SMI-FGRM算法实现攻击效果 代码汇总smifgrm.pytrain.pyadvtest.py 之前已经针对CIFAR10训练了多种分类器&#xff1a; Pytorch | 从零构建AlexNet对CI…

AE Dressler CESAR 1312 Generator Model User Manual

AE Dressler CESAR 1312 Generator Model User Manual

每天40分玩转Django:Django类视图

Django类视图 一、知识要点概览表 类别知识点掌握程度要求基础视图View、TemplateView、RedirectView深入理解通用显示视图ListView、DetailView熟练应用通用编辑视图CreateView、UpdateView、DeleteView熟练应用Mixin机制ContextMixin、LoginRequiredMixin理解原理视图配置U…

建造者模式 Builder Pattern

在创建一个对象的时候&#xff0c;构造器参数有点多&#xff0c;而且有些参数还是可选的&#xff0c;再者还有不少同类型的&#xff0c;那就更应该使用 builder 模式了。 使用 Builder 模式的初衷是 把易变性&#xff08;mutability&#xff09;移动到Builder类&#xff0c;而…

OpenCV-Python实战(11)——边缘检测

一、Sobel 算子 通过 X 梯度核与 Y 梯度核求得图像在&#xff0c;水平与垂直方向的梯度。 img cv2.Sobel(src*,ddepth*,dx*,dy*,ksize*,scale*,delta*,borderType*)img&#xff1a;目标图像。 src&#xff1a;原始图像。 ddepth&#xff1a;目标图像深度&#xff0c;-1 代表…

Github优质项目推荐(第十期)

文章目录 Github优质项目推荐&#xff08;第十期&#xff09;一、【postiz-app】&#xff0c;14.6k stars - 您的终极 AI 社交媒体调度工具二、【lobe-chat】&#xff0c;50.1k stars - AI 聊天框架三、【cobalt】&#xff0c;22.1k stars - 媒体下载器四、【build-your-own-x】…

【Linux】:Linux网络编程基础

1 网络基础概念 计算机网络背景 网络发展 独立模式:计算机之间相互独立; 网络互联:多台计算机连接在一起,完成数据共享 局域网LAN:计算机数量更多了,通过交换机和路由器连接在一起 广域网WAN:将远隔千里的计算机都连在一起 所谓"局域网"和"广域网"只是…

基于Golang的博客系统的设计与实现

全文字数&#xff1a;6040 全文字符数&#xff1a;3753 正文字数&#xff1a;5296 正文字符数&#xff1a;3176 图片数&#xff1a;8 表格数&#xff1a;10 Abstract With the continuous development of the Internet, more and more internet developers will use blogs to…

Type-C接口的拍摄云台

在摄影与摄像的世界里&#xff0c;稳定性是确保画面流畅、清晰的关键因素之一。无论是专业摄影师还是摄影爱好者&#xff0c;都深知在拍摄过程中&#xff0c;任何微小的抖动都可能对最终作品产生不可忽视的影响。为了克服这一挑战&#xff0c;拍摄云台应运而生&#xff0c;成为…

【Go】:Sentinel 动态数据源配置指南

前言 在现代微服务架构中&#xff0c;流量控制是确保系统高可用性和稳定性的关键。Sentinel 是一款由阿里巴巴开源的流量控制组件&#xff0c;它不仅支持熔断降级和流量整形&#xff0c;还能通过动态数据源&#xff08;如本地文件或 Nacos&#xff09;加载规则&#xff0c;从而…

密钥登录服务器

1. 生成 SSH 密钥对 如果您还没有生成密钥对&#xff0c;可以使用以下命令生成&#xff1a; ssh-keygen 在 root 用户的家目录中生成了一个 .ssh 的隐藏目录&#xff0c;内含两个密钥文件&#xff1a;id_rsa 为私钥&#xff0c;id_rsa.pub 为公钥。 在提示时&#xff0c;您可…

Apriori关联规则算法 HNUST【数据分析技术】(2025)

1.理论知识 Apriori是一种常用的数据关联规则挖掘方法&#xff0c;它可以用来找出数据集中频繁出现的数据集合。该算法第一次实现在大数据集上的可行的关联规则提取&#xff0c;其核心思想是通过连接产生候选项及其支持度&#xff0c;然后通过剪枝生成频繁项集。 Apriori算法的…

2025最新版Java面试八股文大全

一、Java并发面试题 1、 ThreadLocal 1.1 谈谈你对ThreadLocal的理解&#xff1f; ThreadLocal的作用主要是做数据隔离&#xff0c;填充的数据只属于当前线程&#xff0c;变量的数据对别的线程而言是相对隔离的。它不是针对程序的全局变量&#xff0c;只是针对当前线程的全局…

tryhackme-Cyber Security 101-Cryptography-Cryptography Basics(加密基础)

目的&#xff1a;了解加密和对称加密的基础知识。 任务1&#xff1a;介绍 你有没有想过如何防止第三方阅读你的消息&#xff1f;您的应用程序 或 Web 浏览器如何与远程服务器建立安全通道&#xff1f;安全是指没有人可以读取或更改交换的数据;此外&#xff0c;我们可以确信我们…

40.2 预聚合和prometheus-record使用

本节重点介绍 : downsample降采样可以降低查询数据量 prometheus原生不支持downsample 实时查询/聚合 VS 预查询/聚合的优缺点 实时查询/聚合条件随意组合&#xff0c;性能差预查询/聚合 性能好&#xff0c;聚合条件需要提前定义 prometheus的预查询/聚合配置举例 downsample…

JavaEE 3大组件 Listener Servlet Filter

1. Listener不熟悉 2. Servlet Servlet: Server Applet&#xff0c;翻译为运行在服务端的Java小程序&#xff0c;是sun公司提供一套规范( 接口 )&#xff0c;用来定义我们的代码怎么写才能被tomcat识别。 本质&#xff1a;接口&#xff0c;一个类想要被tomcat正确识别&…

jmeter并发用户逐步递增压测找性能拐点

jmeter并发用户逐步递增压测找性能拐点 目的&#xff1a; 使用逐层递增的并发压力进行测试&#xff0c;找到单功能的性能拐点&#xff08;一般需要包含四组测试结果&#xff0c;拐点前一组&#xff0c;拐点一组&#xff0c;拐点后两组&#xff09;&#xff0c;统计响应时间、…

overleaf中文生僻字显示不正确,显示双线F

我是不想换全文字体的&#xff0c;只是一个生僻字显示不出来&#xff0c;就想要像word一样&#xff0c;把这个生僻字用包含这个生僻字的字体来显示就好了。 解决步骤&#xff1a; 1、使用如下宏包&#xff1a; \usepackage{xeCJK} %声明宏包&#xff0c;主要用于支持在XeTeX…

音视频入门基础:MPEG2-TS专题(24)——FFmpeg源码中,显示TS流每个packet的pts、dts的实现

音视频入门基础&#xff1a;MPEG2-TS专题系列文章&#xff1a; 音视频入门基础&#xff1a;MPEG2-TS专题&#xff08;1&#xff09;——MPEG2-TS官方文档下载 音视频入门基础&#xff1a;MPEG2-TS专题&#xff08;2&#xff09;——使用FFmpeg命令生成ts文件 音视频入门基础…