C++编程中的六种内存顺序模型

文章目录

  • 前言
  • 为什么要设计内存顺序模型
  • 常见的内存顺序模型
  • 总结

前言

程序员真是一个活到老学到老的职业,一天不学习就会掉队,『内存顺序模型』对于我来说就是一个新的世界,虽然之前写过多线程的服务器,也处理过死锁和竞态条件等问题,但是从来没考虑过内存顺序问题,所以当我第一次看到这个概念时,整个人都是懵的,经过一段时间的学习和了解有了初步的认识,所以简单总结下来,以备后续查看,不多写,慢慢总结。

为什么要设计内存顺序模型

内存顺序模型是为了解决多线程程序中的内存一致性和可见性问题而引入的。在多线程环境下,不同线程可能同时访问和修改共享的内存,这会引发一系列并发性问题,如竞态条件、数据竞争等。内存顺序模型的目的是通过定义不同操作之间的执行顺序和可见性规则,来保证多线程程序的正确性和可预测性。主要原因如下:

  1. 多线程并发问题: 在多线程程序中,线程之间可能并发地读取和写入共享内存,导致数据不一致和不可预测的行为。

  2. 编译器和处理器优化: 编译器和处理器可能会对代码进行优化,例如重排指令以提高性能。这些优化可能会导致操作的执行顺序与代码中的顺序不一致,从而引发问题。

  3. 硬件内存模型: 不同的计算机体系结构有不同的硬件内存模型,即不同的读写操作在不同的条件下可能表现出不同的行为。

  4. 数据依赖性: 在某些情况下,某个操作的结果可能会影响后续操作的执行。内存顺序模型可以帮助定义这种数据依赖性。

内存顺序模型通过定义不同操作之间的关系,如同步、重排等,来解决上述问题。不同的内存顺序模型提供了不同的可见性和同步保证,开发者可以根据自己的需求选择适当的模型。总之,内存顺序模型是为了在多线程环境下提供一种标准化的方式来处理内存一致性和可见性问题,从而使多线程编程更加可靠和可预测,重点关注下第2点和第4点。

有人可能会说,我可以用锁来保证顺序,为什么还要设计内存顺序模型呢?

虽然锁(比如互斥锁)在多线程编程中是一种常见的同步机制,用于保护共享资源,但锁并不能解决所有的并发性问题,而且在某些情况下使用锁可能会引入性能问题。内存顺序模型的设计是为了在不同线程之间定义操作的执行顺序和可见性规则,以解决锁无法解决的一些问题,同时在一些情况下也可以提高性能。

  1. 细粒度同步: 锁通常是用于保护共享资源的,但有时候我们需要更细粒度的同步,比如在不涉及共享资源的情况下也需要保证操作的顺序和可见性。

  2. 原子操作: 内存顺序模型通过定义原子操作的执行顺序和可见性,可以在不使用锁的情况下确保操作的正确执行。这在一些场景下可以避免锁带来的性能开销。

  3. 锁的开销: 锁在某些情况下可能引入较大的性能开销,特别是在高并发环境中。内存顺序模型提供了一种更轻量级的同步机制,可以在一些情况下取代锁,提高性能。

  4. 编译器和处理器优化: 编译器和处理器对代码进行优化时可能会引入指令重排,这可能会导致锁保护下的共享资源出现问题。内存顺序模型通过规定操作的执行顺序,可以避免这种问题。

  5. 原子操作的组合: 内存顺序模型的原子操作可以灵活地组合,以实现更复杂的同步和顺序要求,而不必仅仅依赖于锁。

总之,内存顺序模型和锁在多线程编程中都有其适用的场景。锁通常用于保护共享资源的访问,而内存顺序模型则用于定义操作的执行顺序和可见性,以确保多线程程序的正确性。在多线程编程中,根据具体需求和性能要求,可以选择合适的同步机制。

如果想理解内存顺序,首先要理解两个东西:同一线程中,谁先执行,谁后执行;不同线程中,切换内存的时是否会及时的把依赖数据带过去,对另一个线程可见。

常见的内存顺序模型

C++ 标准库中定义了六种内存顺序模型,用于控制多线程程序中不同操作之间的执行顺序和可见性。这些内存顺序模型通过枚举值表示,从“宽松”到“严格”的次序分别是:

  1. std::memory_order_relaxed 这是最轻量级的内存顺序模型。它不会引入任何额外的同步开销,只保证操作在时间上的顺序是正确的。即使没有明确的同步操作,也不会改变其他线程看到的操作结果。

  2. std::memory_order_consume 在 C++11 中引入,但在 C++20 中被弃用。它主要用于处理数据依赖关系,但在实际中难以实现,已经不推荐使用。

  3. std::memory_order_acquire 在执行当前操作之前,确保所有前面的读操作都完成。它提供了一种读操作同步的保证,确保读操作的结果在后续操作中是可见的。

  4. std::memory_order_release 在执行当前操作之后,确保所有后面的写操作都不会重排到当前操作之前。它提供了一种写操作同步的保证,确保写操作的结果对其他线程是可见的。

  5. std::memory_order_acq_relmemory_order_acquirememory_order_release 的组合。它同时提供了读和写操作的同步保证,适用于需要同时保证读写操作同步的情况。

  6. std::memory_order_seq_cst 是最严格的内存顺序模型,提供了全局的、顺序一致的保证。它确保所有操作按照一个全局的顺序执行,不会引入重排,也保证了最高级别的可见性。

根据具体的多线程编程需求,你可以选择适当的内存顺序模型,以确保正确性和性能。不同的内存顺序模型会引入不同程度的同步开销,因此需要根据实际情况权衡选择。了解这些内存顺序模型可以帮助你在多线程编程中更好地控制操作的执行顺序和可见性,每种模型具体的例子我们后面再慢慢总结。

总结

  • 常见的内存顺序模型前三种:std::memory_order_relaxedstd::memory_order_acquirestd::memory_order_acquire
  • 常见的内存顺序模型后三种:std::memory_order_releasestd::memory_order_acq_relstd::memory_order_seq_cst
  • 其中 `std::memory_order_consume`` 在实际中难以实现,已经在 C++20 中被弃用
  • 编译器和处理器对代码进行优化时可能会引入指令重排,这可能会导致锁保护下的共享资源出现问题
  • 内存顺序模型通过规定操作的执行顺序,可以避免上一个问题
  • 内存顺序和原子操作的引入,是为了无锁的并发编程,提高并发编程的效率
==>> 反爬链接,请勿点击,原地爆炸,概不负责!<<==

或许我就不在你规划的未来
或许她才是你唯一的偏爱
或许我就不该跟你赌未来
或许就不会深陷苦海

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

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

相关文章

linux笔记

1、向某个api地址发送get请求 curl -s -x get http://192.168.0.1:8080/api/vi/groups 2、查看内存消耗最多的前10个进程 ps auxw|head -1;ps auxw|sort -rn -k4|head -10 3、查看系统资源占用情况 top命令&#xff0c;运行之后按c键&#xff0c;可以显示出完整的程序名称 …

Spring Boot简介

文章目录 一、引言1.1 初始化配置1.2 整合第三方框架1.3 后期维护1.4 部署工程1.5 敏捷式开发 二、SpringBoot介绍三、SpringBoot快速入门【重点】3.1 快速构建SpringBoot3.1.1 选择构建项目的类型3.1.2 项目的描述3.1.3 指定SpringBoot版本和需要的依赖3.1.4 导入依赖3.1.5 编…

RabbitMQ死信队列

RabbitMQ死信队列 1、过期时间TTL 过期时间TTL表示可以对消息设置预期的时间&#xff0c;在这个时间内都可以被消费者接收获取&#xff1b;过了之后消息将自动被 删除。RabbitMQ可以对消息和队列设置TTL&#xff0c;目前有两种方法可以设置&#xff1a; 第一种方法是通过队列…

Oracle修改字符集为SIMPLIFIED CHINESE_CHINA.ZHS16GBK

查询字符集 select userenv(language) from dual;修改前字符集为&#xff1a;SIMPLIFIED CHINESE_CHINA.AL32UTF8 SQL> shutdown immediate; Database closed. Database dismounted. ORACLE instance shut down. SQL> startup mount; ORACLE instance started. Total …

【C语言】文件操作 -- 详解

一、什么是文件 磁盘上的文件是文件。 1、为什么要使用文件 举个例子&#xff0c;当我们想实现一个 “通讯录” 程序时&#xff0c;在通讯录中新建联系人、删除联系人等一系列操作&#xff0c;此时的数据存储于内存中&#xff0c;程序退出后所有数据都会随之消失。为了让通讯录…

R语言04-R语言中的列表

概念 在R语言中&#xff0c;列表&#xff08;List&#xff09;是一种复杂的数据结构&#xff0c;用于存储不同类型的元素&#xff0c;包括向量、矩阵、数据框、函数等。列表是一种非常灵活的数据结构&#xff0c;可以将不同类型的数据组合在一起&#xff0c;类似于Python中的字…

第60步 深度学习图像识别:误判病例分析(Pytorch)

基于WIN10的64位系统演示 一、写在前面 上期内容基于Tensorflow环境做了误判病例分析&#xff08;传送门&#xff09;&#xff0c;考虑到不少模型在Tensorflow环境没有迁移学习的预训练模型&#xff0c;因此有必要在Pytorch环境也搞搞误判病例分析。 本期以SqueezeNet模型为…

窗口看门狗

从下往上看: 1. 时钟设置 RCC_APB1PeriphClockCmd(RCC_APB1Periph_WWDG,ENABLE);//使能独立看门狗时钟 WWDG_SetPrescaler(WWDG_Prescaler_8);//看门狗预分频器WWDG counter clock (PCLK1/4096)/8 2.设置窗口值 实际就是设置WWDG_CR的低七位值, 但是这个值要大于0x40(也就是…

【分享】小型园区组网场景

小型园区组网图 在小型园区中&#xff0c;S2700&S3700通常部署在网络的接入层&#xff0c;S5700&S6700通常部署在网络的核心&#xff0c;出口路由器一般选用AR系列路由器。 接入交换机与核心交换机通过Eth-Trunk组网保证可靠性。 每个部门业务划分到一个VLAN中&#…

【Go 基础篇】Go语言分支结构:掌握 if 和 switch,灵活控制程序逻辑

介绍 在编程中&#xff0c;分支结构是一种重要的控制流程&#xff0c;它允许程序根据不同的条件选择不同的执行路径。Go语言提供了两种主要的分支结构&#xff1a;if 和 switch&#xff0c;用于在程序中实现条件判断和多重选择。本篇博客将深入探讨Go语言中的if和switch分支结…

Vulnhub: DriftingBlues: 2靶机

kali&#xff1a;192.168.111.111 靶机&#xff1a;192.168.111.207 信息收集 端口扫描 nmap -A -sC -v -sV -T5 -p- --scripthttp-enum 192.168.111.207 80端口的/blog目录为wordpress wpscan收集wordpress用户和爆破密码 wpscan --url http://driftingblues.box/blog -e…

SpringBoot-yml配置文件的使用与优势

目录 一、什么是yml配置文件&#xff1f; 二、如何在SpringBoot中使用yml配置文件&#xff1f; 三、如何在SpringBoot中注入yml配置文件的属性&#xff1f; Value注解 ConfigurationProperties注解 四、yml配置文件与properties配置文件的区别和优势 区别 优势 五、总结…

非凸联合创始人李佐凡受邀出席复旦DSBA项目座谈会

8月17日&#xff0c;非凸科技联合创始人&CTO李佐凡受邀参加复旦管院数据科学与商业分析专业硕士&#xff08;DS&BA&#xff09;项目发展座谈会&#xff0c;与学校教授、老师在生源背景、课程教学、职业发展、学生培养和企业合作方面进行深入交流&#xff0c;旨在更好地…

【C++练习】普通方法+利用this 设置一个矩形类(Rectangle), 包含私有成员长(length)、 宽(width), 定义一下成员函数

题目 设置一个矩形类(Rectangle), 包含私有成员长(length)、 宽(width), 定义成员函数: void set_ len(int l); //设置长度 设置宽度void set_ wid(int w); 获取长度: int get len(); 获取宽度: int get _wid); 显示周长和面积: v…

如何用Python实现从pdf文件精准抓取数据生成数据库!

要从PDF文件中提取数据并生成数据库&#xff0c;你可以使用Python中的一些库和工具来实现。 1、安装必要的库&#xff1a;确保已安装所需的库。除了之前提到的PyPDF2、pdfminer.six和pdftotext之外&#xff0c;你可能还需要其他的库来处理提取的数据和数据库操作。例如&#x…

民族传统文化分享系统uniapp 微信小程序

管理员、用户可通过Android系统手机打开系统&#xff0c;注册登录后可进行管理员后端&#xff1b;首页、个人中心、用户管理、知识分类管理、知识资源管理、用户分享管理、意见反馈、系统管理&#xff0c;用户前端&#xff1b;首页、知识资源、用户分享、我的等。 本系统的使用…

GO-vscode远程开发和调试

本文内容主要包括&#xff1a; 概述&#xff1a; 主要就是把代码放到服务器上然后远程去开发和调试 工具&#xff1a; vscode 远程端&#xff1a; linux 一.安装远程插件 vscode安装Remote - SSH&#xff0c;Remote Explorer&#xff0c;Remote Development&#xff0c…

4.8 C++ Boost 应用JSON解析库

property_tree 是 Boost 库中的一个头文件库&#xff0c;用于处理和解析基于 XML、Json 或者 INFO 格式的数据。 property_tree 可以提供一个轻量级的、灵活的、基于二叉数的通用容器&#xff0c;可以处理包括简单值&#xff08;如 int、float&#xff09;和复杂数据结构&#…

C++最易读手撸神经网络两隐藏层(任意Nodes每层)梯度下降230820a

这是史上最简单、清晰&#xff0c;最易读的…… C语言编写的 带正向传播、反向传播(Forward ……和Back Propagation&#xff09;……任意Nodes数的人工神经元神经网络……。 大一学生、甚至中学生可以读懂。 适合于&#xff0c;没学过高数的程序员……照猫画虎编写人工智能、…

矿井水处理技术离子交换树脂法

矿井水除氟的要求一般是处理后水中的含氟量≤1.0mg/L。氟化物含量高的原水往往呈偏碱性&#xff0c;pH值常大于7.5。利用阴离子交换树脂上的可交换阴离子&#xff0c;去交换水中的氟离子&#xff0c;达到除氟目的。氟离子的选择交换性较大&#xff0c;树脂上的SO42-、Cl-等阴离…