[知识点] 内存顺序属性的用途和行为
C++标准库中定义了以下几种内存顺序属性:
- std::memory_order_relaxed
- std::memory_order_consume
- std::memory_order_acquire
- std::memory_order_release
- std::memory_order_acq_rel
- std::memory_order_seq_cst
1. std::memory_order_relaxed
 
- 定义:不提供同步或顺序保证,只保证原子操作本身的原子性。
- 用途:适用于不需要同步的情况下,用于计数器等场景。
- 行为:操作之间可以自由重排序,其他线程可能看到不同的操作顺序。
#include <atomic>
#include <iostream>
#include <thread>// 计数器,用于多线程递增
std::atomic<int> counter(0);void increment() {for (int i = 0; i < 1000; ++i) {// 使用 memory_order_relaxed 进行原子加操作// 不保证任何顺序,只保证原子性counter.fetch_add(1, std::memory_order_relaxed);}
}int main() {std::thread t1(increment);std::thread t2(increment);t1.join();t2.join();// 输出最终的计数器值std::cout << "Counter: " << counter.load(std::memory_order_relaxed) << std::endl;return 0;
}2. std::memory_order_consume
 
- 定义:专用于指针依赖的消费操作,确保后续依赖操作的顺序。
- 用途:用于消费操作,确保依赖指针的操作不会被重排序到消费操作之前。
- 行为:类似于 memory_order_acquire,但仅保证指针依赖的顺序。
#include <atomic>
#include <iostream>
#include <thread>// 原子指针,指向整数数据
std::atomic<int*> p;
int data;void producer() {data = 42;// 使用 memory_order_release 存储指针// 确保 data 的写入在存储指针之前完成p.store(&data, std::memory_order_release);
}void consumer() {int* ptr;// 使用 memory_order_consume 加载指针// 确保指针依赖的操作不会被重排序while (!(ptr = p.load(std::memory_order_consume)));// 输出指针指向的数据std::cout << "Data: " << *ptr << std::endl;
}int main() {std::thread t1(producer);std::thread t2(consumer);t1.join();t2.join();return 0;
}3. std::memory_order_acquire
 
- 定义:获取操作,确保后续读写操作不会被重排序到获取操作之前。
- 用途:用于加载操作,以确保加载后的操作看到的是最新的数据。
- 行为:获取操作之前的读写操作可能被重排序,但之后的操作不会。
#include <atomic>
#include <iostream>
#include <thread>// 标志变量,用于同步
std::atomic<int> flag(0);
int data = 0;void writer() {data = 42;// 使用 memory_order_release 存储标志// 确保 data 的写入在存储标志之前完成flag.store(1, std::memory_order_release);
}void reader() {// 使用 memory_order_acquire 加载标志// 确保标志被加载后,读取 data 的操作不会被重排序while (flag.load(std::memory_order_acquire) != 1);// 输出 data 的值std::cout << "Data: " << data << std::endl;
}int main() {std::thread t1(writer);std::thread t2(reader);t1.join();t2.join();return 0;
}4. std::memory_order_release
 
- 定义:释放操作,确保之前的读写操作不会被重排序到释放操作之后。
- 用途:用于存储操作,以确保存储前的所有操作完成。
- 行为:释放操作之后的读写操作可能被重排序,但之前的操作不会。
#include <atomic>
#include <iostream>
#include <thread>// 标志变量,用于同步
std::atomic<int> flag(0);
int data = 0;void writer() {data = 42;// 使用 memory_order_release 存储标志// 确保 data 的写入在存储标志之前完成flag.store(1, std::memory_order_release);
}void reader() {// 使用 memory_order_acquire 加载标志// 确保标志被加载后,读取 data 的操作不会被重排序while (flag.load(std::memory_order_acquire) != 1);// 输出 data 的值std::cout << "Data: " << data << std::endl;
}int main() {std::thread t1(writer);std::thread t2(reader);t1.join();t2.join();return 0;
}5. std::memory_order_acq_rel
 
- 定义:获取和释放操作的组合,适用于读-修改-写操作。
- 用途:用于原子操作,如 compare_exchange,以确保操作的前后都不会被重排序。
- 行为:操作之前和之后的读写操作都不会被重排序。
#include <atomic>
#include <iostream>
#include <thread>// 原子计数器,用于多线程递增
std::atomic<int> counter(0);void increment() {for (int i = 0; i < 1000; ++i) {int expected = counter.load(std::memory_order_relaxed);// 使用 memory_order_acq_rel 进行比较并交换操作// 确保操作之前和之后的读写顺序while (!counter.compare_exchange_weak(expected, expected + 1, std::memory_order_acq_rel));}
}int main() {std::thread t1(increment);std::thread t2(increment);t1.join();t2.join();// 输出最终的计数器值std::cout << "Counter: " << counter.load(std::memory_order_relaxed) << std::endl;return 0;
}6. std::memory_order_seq_cst
 
- 定义:获取和释放操作的组合,适用于读-修改-写操作。
- 用途:用于原子操作,如 compare_exchange,以确保操作的前后都不会被重排序。
- 行为:操作之前和之后的读写操作都不会被重排序。
#include <atomic>
#include <iostream>
#include <thread>// 原子变量
std::atomic<int> x(0), y(0);
int r1, r2;void thread1() {// 使用 memory_order_seq_cst 存储 x// 确保全局顺序一致x.store(1, std::memory_order_seq_cst);// 使用 memory_order_seq_cst 加载 y// 确保全局顺序一致r1 = y.load(std::memory_order_seq_cst);
}void thread2() {// 使用 memory_order_seq_cst 存储 y// 确保全局顺序一致y.store(1, std::memory_order_seq_cst);// 使用 memory_order_seq_cst 加载 x// 确保全局顺序一致r2 = x.load(std::memory_order_seq_cst);
}int main() {std::thread t1(thread1);std::thread t2(thread2);t1.join();t2.join();// 输出结果std::cout << "r1: " << r1 << ", r2: " << r2 << std::endl;return 0;
}总结
- std::memory_order_relaxed: 最弱的同步和顺序保证,仅保证原子操作本身的原子性。
- std::memory_order_consume: 专用于指针依赖,确保后续依赖操作的顺序。
- std::memory_order_acquire: 获取操作,确保后续读写操作不会被重排序到获取操作之前。
- std::memory_order_release: 释放操作,确保之前的读写操作不会被重排序到释放操作之后。
- std::memory_order_acq_rel: 获取和释放操作的组合,适用于读-修改-写操作。
- std::memory_order_seq_cst: 顺序一致性操作,提供最强的同步和顺序保证。
相关文章:
[知识点] 内存顺序属性的用途和行为
C标准库中定义了以下几种内存顺序属性: std::memory_order_relaxedstd::memory_order_consumestd::memory_order_acquirestd::memory_order_releasestd::memory_order_acq_relstd::memory_order_seq_cst 1. std::memory_order_relaxed 定义:不提供同步…...
JAVA Mongodb 深入学习(二)索引的创建和优化
一、常用索引类型 1、单个索引 单个索引的创建 db.你的表名.createIndex({"你的字段名":1}) 单个索引的创建且是唯一索引 db.你的表名.createIndex({"你的字段名":1}),{ unique: true }) 2、复合索引 将多个过滤的字段,做成索引,…...
 
转让北京劳务分包地基基础施工资质条件和流程
地基基础资质转让流程是怎样的?对于企业来说,资质证书不仅是实力的证明,更是获得工程承包的前提。而在有了资质证书后,企业才可以安心的准备工程投标,进而在工程竣工后获得收益。而对于从事地基基础工程施工的企业,需…...
 
Python基础——字符串
一、Python的字符串简介 Python中的字符串是一种计算机程序中常用的数据类型【可将字符串看作是一个由字母、数字、符号组成的序列容器】,字符串可以用来表示文本数据。 通常使用一对英文的单引号()或者双引号(")…...
AP的数据库性能到底重要吗?
先说结论:没那么重要。甚至可能不重要。 我用我的经历和分析给大家说说。诸位看看如何。 不重要的观点是不是不能接受? 因为这些是站在我们角度觉得的。而实际上使用者(业务或者用户),真的不太在乎我们所在乎的。 …...
 
Vue3【二】 VSCode需要安装的Vue语法插件
VSCode需要安装的 适配Vue3的插件 Vue-Official插件安装...
 
设置路径别名
一、描述 如果想要给路径设置为别名,就是常见的有些项目前面的引入文件通过开头的,也就是替换了一些固定的文件路径,怎么配置。 二、配置 import { defineConfig } from vite import react from vitejs/plugin-react import path from path…...
 
人事信息管理系统(Java+MySQL)
一、项目背景 在现代企业中,管理大量员工的工作信息、薪资、请假、离职等事务是一项非常繁琐和复杂的任务。传统的手工管理方式不仅效率低下,而且容易出错。为了提高人事管理的效率,减少人工操作带来的错误,企业迫切需要一个高效…...
Python 中生成器与普通函数的区别
在Python中,生成器和普通函数有一些区别。 生成器使用 yield 语句从函数中返回一个值,而不是使用 return 语句。当生成器函数被调用时,它会返回一个迭代器对象,而非立即执行函数体内的代码。 生成器函数可以通过多次调用 yield 语…...
 
最小栈、栈的弹出(C++)
1.最小栈 思路分析: 代码: class MinStack { public:MinStack() {}void push(int val) {st.push(val);//两种情况需要更新最小值//1.最小栈为空(就是存最小值的那个栈)//2.插入的值小于或等于最小栈的栈顶元素if(minstack.empty()||minstack.top()>…...
 
20240607每日通信--------VUE3前端引入scoket-io,后端引入Netty-SocketIO,我成功了,希望一起交流沟通
无语 前置: VUE3 前端集成scoket-io socket.io-client Sringboot 3.0JDK17集成Netty-SocketIO Netty-SocketIO 失败原因一: 前期决定要写demo时候,单独了解了,后端引入Netty-SocketIO注意事项,详见我先头写的博客 前…...
 
Tomcat源码解析(八):一个请求的执行流程(附Tomcat整体总结)
Tomcat源码系列文章 Tomcat源码解析(一):Tomcat整体架构 Tomcat源码解析(二):Bootstrap和Catalina Tomcat源码解析(三):LifeCycle生命周期管理 Tomcat源码解析(四):StandardServer和StandardService Tomcat源码解析(五)&…...
python使用gdb进行堆栈查看与调试
以ubuntu示例,先安装gdb与python-dbg,dbg按照python版本安装 apt install -y gdb python3.10-dbg 使用top查看python进程,使用gdb操作python进程 gdb python3 6618 加载环境 source /usr/share/gdb/auto-load/usr/bin/python3.10-gdb.py…...
【DevOps】路由与路由器详细介绍:原理、功能、类型及应用场景
目录 一、路由详细介绍 1、什么是路由? 2、路由的基本原理 3、 路由协议 静态路由 动态路由 4、 路由表 5、 路由算法 6、路由的优缺点 优点 缺点 7、 路由应用场景 二、路由器详细介绍 1、什么是路由器? 2、 路由器的工作原理 3、路由器…...
 
【WP|9】深入解析WordPress [add_shortcode]函数
add_shortcode 是 WordPress 中一个非常强大的函数,用于创建自定义的短代码(shortcodes)。短代码是一种简洁的方式,允许用户在内容中插入动态的、可重用的功能。通过 add_shortcode,开发者可以定义自己的短代码&#x…...
Qt QStackedWidget类详细分析
一.定义 QStackedWidget类是一个容器控件,它提供了一个堆叠的页面布局方式,每个页面可以包含一个子部件。在QStackedWidget中,只有当前活动的页面是可见的,其他页面会被隐藏起来。 QStackedWidget类的常用方法包括: a…...
Java数据结构与算法(leetcode热题881. 救生艇)
前言 救生艇属于贪心算法,解题之前条件一定要归纳好。题目中存在3个要求: 1.一艘船最多坐2人 2.船数要求最小 3.每艘船重量小于limit 意味着体重较轻的两人可以同乘一艘救生艇。 . - 力扣(LeetCode) 实现原理 1.重量大的有…...
react+wijmo所遇问题
1.官网地址:https://demo.mescius/wijmo/demos/Grid/Overview/react 别进中文地址,注意后缀mescius有没有.cn有的话删掉,那个没有触发方法和各类API,组件也不全 2.中文地址:(不太好用)&#x…...
 
手撕设计模式——克隆对象之原型模式
1.业务需求  大家好,我是菠菜啊,前俩天有点忙,今天继续更新了。今天给大家介绍克隆对象——原型模式。老规矩,在介绍这期之前,我们先来看看这样的需求:《西游记》中每次孙悟空拔出一撮猴毛吹一下&#x…...
 
LangChain基础知识入门
LangChain的介绍和入门 1 什么是LangChain LangChain由 Harrison Chase 创建于2022年10月,它是围绕LLMs(大语言模型)建立的一个框架,LLMs使用机器学习算法和海量数据来分析和理解自然语言,GPT3.5、GPT4是LLMs最先进的代…...
 
深度学习在微纳光子学中的应用
深度学习在微纳光子学中的主要应用方向 深度学习与微纳光子学的结合主要集中在以下几个方向: 逆向设计 通过神经网络快速预测微纳结构的光学响应,替代传统耗时的数值模拟方法。例如设计超表面、光子晶体等结构。 特征提取与优化 从复杂的光学数据中自…...
Go 语言接口详解
Go 语言接口详解 核心概念 接口定义 在 Go 语言中,接口是一种抽象类型,它定义了一组方法的集合: // 定义接口 type Shape interface {Area() float64Perimeter() float64 } 接口实现 Go 接口的实现是隐式的: // 矩形结构体…...
 
ESP32读取DHT11温湿度数据
芯片:ESP32 环境:Arduino 一、安装DHT11传感器库 红框的库,别安装错了 二、代码 注意,DATA口要连接在D15上 #include "DHT.h" // 包含DHT库#define DHTPIN 15 // 定义DHT11数据引脚连接到ESP32的GPIO15 #define D…...
全面解析各类VPN技术:GRE、IPsec、L2TP、SSL与MPLS VPN对比
目录 引言 VPN技术概述 GRE VPN 3.1 GRE封装结构 3.2 GRE的应用场景 GRE over IPsec 4.1 GRE over IPsec封装结构 4.2 为什么使用GRE over IPsec? IPsec VPN 5.1 IPsec传输模式(Transport Mode) 5.2 IPsec隧道模式(Tunne…...
 
技术栈RabbitMq的介绍和使用
目录 1. 什么是消息队列?2. 消息队列的优点3. RabbitMQ 消息队列概述4. RabbitMQ 安装5. Exchange 四种类型5.1 direct 精准匹配5.2 fanout 广播5.3 topic 正则匹配 6. RabbitMQ 队列模式6.1 简单队列模式6.2 工作队列模式6.3 发布/订阅模式6.4 路由模式6.5 主题模式…...
 
android13 app的触摸问题定位分析流程
一、知识点 一般来说,触摸问题都是app层面出问题,我们可以在ViewRootImpl.java添加log的方式定位;如果是touchableRegion的计算问题,就会相对比较麻烦了,需要通过adb shell dumpsys input > input.log指令,且通过打印堆栈的方式,逐步定位问题,并找到修改方案。 问题…...
鸿蒙(HarmonyOS5)实现跳一跳小游戏
下面我将介绍如何使用鸿蒙的ArkUI框架,实现一个简单的跳一跳小游戏。 1. 项目结构 src/main/ets/ ├── MainAbility │ ├── pages │ │ ├── Index.ets // 主页面 │ │ └── GamePage.ets // 游戏页面 │ └── model │ …...
 
【Linux】Linux安装并配置RabbitMQ
目录 1. 安装 Erlang 2. 安装 RabbitMQ 2.1.添加 RabbitMQ 仓库 2.2.安装 RabbitMQ 3.配置 3.1.启动和管理服务 4. 访问管理界面 5.安装问题 6.修改密码 7.修改端口 7.1.找到文件 7.2.修改文件 1. 安装 Erlang 由于 RabbitMQ 是用 Erlang 编写的,需要先安…...
高防服务器价格高原因分析
高防服务器的价格较高,主要是由于其特殊的防御机制、硬件配置、运营维护等多方面的综合成本。以下从技术、资源和服务三个维度详细解析高防服务器昂贵的原因: 一、硬件与技术投入 大带宽需求 DDoS攻击通过占用大量带宽资源瘫痪目标服务器,因此…...
精益数据分析(98/126):电商转化率优化与网站性能的底层逻辑
精益数据分析(98/126):电商转化率优化与网站性能的底层逻辑 在电子商务领域,转化率与网站性能是决定商业成败的核心指标。今天,我们将深入解析不同类型电商平台的转化率基准,探讨页面加载速度对用户行为的…...
