C++中的原子操作:原子性、内存顺序、性能优化与原子变量赋值
一、原子操作与原子性
原子操作(atomic operation)是并发编程中的一个核心概念,指的是在多线程环境中,一个操作一旦开始,就不会被其他线程的操作打断,直至该操作完成。这种不可分割的特性保证了操作的原子性,即要么全部做完,要么全部不做。原子操作在多线程编程中非常重要,因为它能有效避免数据竞争和条件竞争等问题,从而确保程序的正确性和稳定性。
C++11引入了原子操作,通过<atomic>
头文件提供了一系列原子类型和函数,如std::atomic<T>
,用于确保对共享数据的操作是原子的。原子类型提供了一系列成员函数来执行原子操作,这些操作包括加载(load)、存储(store)、加法(fetch_add、add)、减法(fetch_sub、sub)、交换(exchange)和比较并交换(compare_exchange_weak、compare_exchange_strong)等。
二、原子变量赋值操作
在C++中,原子变量赋值是通过std::atomic
模板类实现的,提供了多种方法来对原子变量进行赋值和修改。以下是一些常见的原子变量赋值操作及其示例:
-
基本赋值
基本赋值操作是使用赋值运算符(=)直接将一个新值赋给原子变量。例如:
std::atomic<int> counter(0); // 声明一个原子整数变量,初始值为0
counter = 10; // 将10赋给counter
-
原子加法与减法
使用
fetch_add
、add
等成员函数可以实现原子加法操作,fetch_sub
、sub
等成员函数可以实现原子减法操作。fetch_add
和fetch_sub
返回加法或减法操作之前的值,而add
和sub
返回加法或减法操作之后的值。例如:
std::atomic<int> counter(0);int oldValue = counter.fetch_add(1); // 将counter的值加1,并返回加1之前的值int newValue = counter.add(5); // 将counter的值加5,并返回加5之后的值oldValue = counter.fetch_sub(3); // 将counter的值减3,并返回减3之前的值newValue = counter.sub(2); // 将counter的值减2,并返回减2之后的值
-
原子交换
使用
exchange
成员函数可以实现原子交换操作,即将原子变量的当前值与一个新值进行交换,并返回交换之前的值。例如:
std::atomic<int> counter(5);
int oldValue = counter.exchange(10); // 将counter的值与10进行交换,并返回交换之前的值5
-
原子比较并交换
使用
compare_exchange_weak
或compare_exchange_strong
成员函数可以实现原子比较并交换操作。这两个函数都尝试将原子变量的当前值与一个期望值进行比较,如果相等,则将其设置为一个新值,并返回true;如果不相等,则返回false,并将期望值更新为当前值。compare_exchange_weak
在某些平台上可能会由于性能优化而偶尔失败(即使当前值与期望值相等),而compare_exchange_strong
则保证在当前值与期望值相等时一定会成功。例如:
std::atomic<int> counter(5);int expected = 5;bool success = counter.compare_exchange_strong(expected, 10); // 如果counter的值等于5,则将其设置为10,并返回true;否则返回false,并将expected更新为counter的当前值
- 原子性值传递
有时,我们需要将一个原子变量的值从一个对象复制到另一个对象。这可以通过load()
和store()
成员函数来实现。load()
函数用于从原子变量中加载当前值,而store()
函数用于将一个新值存储到原子变量中。以下是一个示例:
std::atomic<int> original(5); // 声明一个原子整数变量,初始值为5
std::atomic<int> target(0); // 声明另一个原子整数变量,初始值为0// 将original的值加载到局部变量中(虽然在这个例子中不是必需的,但展示了load的用法)
int value = original.load();// 直接将original的值存储到target中,这是一个原子操作
target.store(original.load()); // 将原始对象的值存储到目标对象// 此时,target的值也是5
三、内存顺序
内存顺序(Memory Order)是多线程编程中一个非常重要的概念,它定义了在多处理器或多核环境中,内存访问的次序。C++11标准明确引入了内存顺序,用于指定原子操作的顺序性,以避免多线程环境下的数据竞争问题。
C++11标准定义了多种内存顺序类型,包括memory_order_relaxed
、memory_order_consume
、memory_order_acquire
、memory_order_release
、memory_order_acq_rel
和memory_order_seq_cst
等。在实际编程中,开发者需要根据操作的目的和上下文环境来确定合适的内存顺序。
选择合适的内存顺序可以在保证正确性的前提下提高性能。例如,使用memory_order_relaxed
可以放松对内存顺序的要求,从而减少同步开销,但可能会引入数据竞争的风险。相反,使用memory_order_seq_cst
可以确保最强的顺序性保证,但可能会增加同步开销。
四、性能优化
原子操作通过避免锁的使用,减少了线程之间的竞争和上下文切换开销,从而提高了多线程程序的性能。然而,性能优化并非一味追求宽松的内存顺序,而需要在正确性和性能之间取得平衡。
以下是一些性能优化的建议:
-
选择合适的内存顺序:在保证线程安全的前提下,尽量使用宽松的内存顺序可以减少同步操作,从而提升性能。然而,过度放宽内存顺序可能会导致难以调试的并发问题。
-
利用硬件特性:不同CPU架构和编译器的实现对原子操作的支持和优化程度不同。深入理解平台特性,利用硬件提供的原子性支持和缓存一致性机制,可以进一步提高程序的性能。
-
减少不必要的同步:通过合理设计算法和数据结构,减少线程间的同步需求。例如,使用无锁数据结构、读写锁等高级同步机制,可以在保持线程安全的同时,减少同步开销。
-
避免忙等待:在需要等待某个条件成立时,避免使用忙等待(busy-waiting)的方式。忙等待会消耗大量的CPU资源,并可能导致性能下降。相反,可以使用条件变量、信号量等同步机制来实现高效的等待和通知机制。
综上所述,深入理解C++中的原子操作、原子性、内存顺序、性能优化以及原子变量赋值操作,对于编写高效且正确的并发代码至关重要。通过合理选择内存顺序、利用硬件特性、减少不必要的同步和避免忙等待等策略,可以在保证程序正确性的同时实现性能的优化。
相关文章:

C++中的原子操作:原子性、内存顺序、性能优化与原子变量赋值
一、原子操作与原子性 原子操作(atomic operation)是并发编程中的一个核心概念,指的是在多线程环境中,一个操作一旦开始,就不会被其他线程的操作打断,直至该操作完成。这种不可分割的特性保证了操作的原子…...

游戏引擎学习第19天
介绍 这段内容描述了开发者在进行游戏开发时,对于音频同步和平台层的理解和调整的过程。以下是更详细的复述: 开发者表达了他希望今天继续进行的工作内容。他提到,昨天他讲解了一些关于音频的内容,今天他想稍微深入讲解一下他正…...

RocketMQ: 专业术语以及相关问题解决
概述 要了解 RocketMQ 的多个关键特性的实现原理,并对消息中间件遇到的各种问题进行解决我们引用 JMS 规范 与 CORBA Notification 规范,规范为我们设计系统指明了方向但是仍有不少问题规范没有提及,对于消息中间件又至关重要RocketMQ 并不遵…...

C++ 类和对象中的 拷贝构造 和 运算符重载
构造函数中可以添加参数并添加默认值构成缺省构造,如果我们在构造函数的参数中加上自身类型类的引用和其他给出默认值的参数则会构成一种特殊的构造函数叫做———拷贝构造函数 1.拷贝构造 拷贝构造的特点: 1.拷贝构造函数是构造函数的一个重载 2.拷…...

el-table最大高度无法滚动
解决el-table同时使用fixed和计算的最大高度时固定右边的列无法跟随滚动的问题 原因:el-table组件会根据传入的 max-height 计算表格内容部分 和 fixed部分的最大高度,以此来生成滚动条和产生滚动效果,当传入的 max-height 为一个计算的高度…...

Vscode写markdown快速插入python代码
如图当我按下快捷键CRTLSHIFTK 自动出现python代码片段 配置方法shortcuts’ 打开这个json文件 输入 {"key": "ctrlshiftk","command": "editor.action.insertSnippet","when": "editorTextFocus","args&…...

基于 NCD 与优化函数结合的非线性优化 PID 控制
基于 NCD 与优化函数结合的非线性优化 PID 控制 1. 引言 NCD(Normalized Coprime Factorization Distance)优化是一种用于非线性系统的先进控制方法。通过将 NCD 指标与优化算法结合,可以在动态调整控制参数的同时优化控制器性能。此方法特别…...

【数据分析】基于GEE实现大津算法提取洞庭湖流域水体
大津算法提取水体 1.写在前面2.洞庭湖水体识别1.写在前面 最大类间方差法,也称为Otsu或大津法,是一种高效的图像二值化算法,由日本学者Otsu于1979年提出。该算法基于图像的频率分布直方图,假设图像包含两类像素(前景和背景),并计算出一个最佳阈值,以最大化类间方差,从…...

计算机网络安全 —— 报文摘要算法 MD5
一、报文摘要算法基本概念 使用加密通常可达到报文鉴别的目的,因为伪造的报文解密后一般不能得到可理解的内容。但简单采用这种方法,计算机很难自动识别报文是否被篡改。另外,对于不需要保密而只需要报文鉴别的网络应用,对整个…...

LeetCode 746. 使用最小花费爬楼梯 java题解
https://leetcode.cn/problems/min-cost-climbing-stairs/description/ 优化:可以不用dp数组,用变量,节省空间。 class Solution {public int minCostClimbingStairs(int[] cost) {int lencost.length;int[] dpnew int[len1];dp[0]0;//爬到0…...

Kubernetes的pod控制器
文章目录 一,什么是pod控制器二,pod控制器类型(重点)1.ReplicaSet2.Deployment3.DaemonSet4.StatefulSet5.Job6.Cronjob 三,pod与控制器的关系1.Deployment2.SatefulSet2.1StatefulSet组成2.2headless的由来2.3有状态服…...

ArcMap 处理栅格数据地形图配准操作
ArcMap 处理栅格数据地形图配准操作今天分享 一、地形图配准 1、绘图 点击 开始绘制,四条线 2、地理配准 1)点击弹出 2)画控制点 关闭自动校正 画线 从焦点向外划线,然后邮件输入坐标弹出框,填写相应内容,…...

comprehension
1.读题---猜---文章主题 只读题目,不读选项 2.文章--定位 3.用文章对应选项 1 be based on be dependent upon 2 fruitful adj.富有成效的;硕果累累的; 3 unfruitful adj.徒然的,无益的,没有结果的 4 desperately adv.拼命地&#x…...

开源宝藏:Smart-Admin 重复提交防护的 AOP 切面实现详解
首先,说下重复提交问题,基本上解决方案,核心都是根据URL、参数、token等,有一个唯一值检验是否重复提交。 而下面这个是根据用户id,唯一值进行判定,使用两种缓存方式,redis和caffeineÿ…...

使用 npm 安装 Electron 作为开发依赖
好的,下面是一个使用 npm pack 和 npm install 命令来打包和安装离线版本的 npm 包的具体示例。我们将以 electron 为例,演示如何在有网络连接的机器上打包 electron,然后在没有网络连接的机器上安装它。 步骤 1: 在有网络连接的机器上打包 …...

JavaWeb之综合案例
前言 这一节讲一个案例 1. 环境搭建 然后就是把这些数据全部用到sql语句中执行 2.查询所有-后台&前台 我们先写后台代码 2.1 后台 2.2 Dao BrandMapper: 注意因为数据库里面的名称是下划线分割的,我们类里面是驼峰的,所以要映射 …...

MySQL 报错:1137 - Can‘t reopen table
MySQL 报错:1137 - Can’t reopen table 1. 问题 对临时表查询: select a.ts_code,a.tsnum,b.tsnum from (select t.ts_code ,count(*) tsnum from tmp_table t group by t.ts_code having count(*) > 20 and count(*)< 50 ) a ,(select t.ts_…...

Claude3.5-Sonnet和GPT-4o怎么选(附使用链接)
随着人工智能模型的不断进化,传统的评估标准已经逐渐变得陈旧和不再适用。以经典的“喝水测试”为例,过去广泛应用于检测模型能力,但现如今即便是国内的一些先进模型,也能够轻松答对这些简单的问题。因此,我们亟需引入…...

使用itextpdf进行pdf模版填充中文文本时部分字不显示问题
在网上找了很多种办法 都解决不了; 最后发现是文本域字体设置出了问题; 在这不展示其他的代码 只展示重要代码; 1 引入扩展包 <dependency><groupId>com.itextpdf</groupId><artifactId>itext-asian</artifactId><version>5.2.0</v…...

java-贪心算法
1. 霍夫曼编码(Huffman Coding) 描述: 霍夫曼编码是一种使用变长编码表对数据进行编码的算法,由David A. Huffman在1952年发明。它是一种贪心算法,用于数据压缩。霍夫曼编码通过构建一个二叉树(霍夫曼树&a…...

OpenCV和Qt坐标系不一致问题
“ OpenCV和QT坐标系导致绘图精度下降问题。” OpenCV和Qt常用的坐标系都是笛卡尔坐标系,但是细微处有些不同。 01 — OpenCV坐标系 OpenCV是图像处理库,是以图像像素为一个坐标位置,即一个像素对应一个坐标,所以其坐标系也叫图像…...

前端VUE项目启动方式
将VUE项目的前端项目运行起来,整个过程非常简单,预计5分钟就可以完成,取决于大家的网速。 项目运行先安装Node.js Windows 安装 Node.js 指南:http://www.iocoder.cn/NodeJS/windows-install(opens new window) Mac 安装 Node.js…...

Python小白学习教程从入门到入坑------习题课5(基础巩固)
目录 实战题 1、“千年虫”是什么虫? 2、模拟京东购物流程 3、模拟12306火车票订票流程 4、模拟手机通讯录 实战题 1、“千年虫”是什么虫? 要求:已知一个列表中存储的是员工的出生年份 [88,89,90,98,00,99] 由于时间比较久,出生的年份均为2位整数…...

飞凌嵌入式T113-i开发板RISC-V核的实时应用方案
随着市场对嵌入式设备的功能需求越来越高,集成了嵌入式处理器和实时处理器的主控方案日益增多,以便更好地平衡性能与效率——实时核负责高实时性任务,A核处理复杂任务,两核间需实时交换数据。然而在数据传输方面,传统串…...

基于Java后台实现百度、高德和WGS84坐标的转换实战
目录 前言 一、需求的缘由 1、百度坐标拾取 2、高德坐标拾取 3、不同地图的坐标展示 二、后端坐标偏移转换处理 1、相关类库介绍 2、coordtransorm类图介绍 3、后台实际转换 三、总结 前言 在当今数字化时代,地理位置信息的精确性和实时性对于各种应用至…...

SQL,力扣题目1635,Hopper 公司查询 I
一、力扣链接 LeetCode_1635 二、题目描述 表: Drivers ---------------------- | Column Name | Type | ---------------------- | driver_id | int | | join_date | date | ---------------------- driver_id 是该表的主键(具有唯一值的列)。 该表的每一行…...

Android 分区相关介绍
目录 一、MTK平台 1、MTK平台分区表配置 2、MTK平台刷机配置表 3、MTK平台分区表配置不生效 4、Super分区的研究 1)Super partition layout 2)Block device table 二、高通平台 三、展锐平台 四、相关案例 1、Super分区不够导致编译报错 经验…...

JMeter监听器与压测监控之 InfluxDB
1. 简介 在本文中,我们将介绍如何在 Kali Linux 上通过 Docker 安装 InfluxDB,并使用 JMeter 对其进行性能监控。InfluxDB 是一个高性能的时序数据库,而 JMeter 是一个开源的性能测试工具,可以用于对各种服务进行负载测试和性能监…...

信息安全管理与评估赛项(网络安全)--应急响应专项训练
web1 题目来源:https://mp.weixin.qq.com/s/89IS3jPePjBHFKPXnGmKfA 题目 1.攻击者的shell密码2.攻击者的IP地址3.攻击者的隐藏账户名称4.攻击者挖矿程序的矿池域名(仅域名)5.有实力的可以尝试着修复漏洞靶机 用户:administrator密码:Zgsfadmin.com题解 攻击者…...

ElasticSearch学习篇18_《检索技术核心20讲》LevelDB设计思想
目录 一些常见的设计思想以及基于LSM树的LevelDB是如何利用这些设计思想优化存储、检索效率的。 几种常见的设计思想 索引和数据分离减少磁盘IO读写分离分层思想 LevelDB的设计思想 读写分离设计分层设计与延迟合并LRU缓存加速检索 几种常见设计思想 索引与数据分离 索引…...