c++原子操作 std::atomic

1.概要 

std::atomic 是 C++11 标准库引入的一个模板类,用于表示一个原子类型。原子类型是一种特殊的类型,其对象的操作(如读取、写入、修改等)在多线程环境中是原子的,即这些操作是不可中断的,并且在多线程之间是不可见的。换句话说,对原子类型的操作是线程安全的。

原子操作通常用于多线程编程中的同步和通信,因为它们可以确保在多线程环境中对共享数据的访问是安全的,从而避免了数据竞争(data race)和其他并发问题。

std::atomic 模板类提供了多种成员函数和运算符重载,用于执行原子操作,例如:

  • load():从原子对象中加载值。
  • store():将值存储到原子对象中。
  • exchange():以原子方式将新值存储在原子对象中,并返回旧值。
  • compare_exchange_weak() 和 compare_exchange_strong():以原子方式比较并交换值。
  • 运算符重载,如 ++--+=-= 等,用于执行原子算术运算。

使用 std::atomic 可以大大简化多线程编程中的同步工作,因为你可以直接对原子类型进行操作,而无需显式使用互斥体(mutexes)、条件变量(condition variables)或其他同步机制。然而,你仍然需要注意确保逻辑上的正确性,以避免出现死锁、饥饿或其他并发问题。

下面是一个简单的示例,展示了如何使用 std::atomic 来实现一个线程安全的计数器:

#include <iostream>  
#include <thread>  
#include <atomic>  std::atomic<int> counter(0); // 初始化一个原子计数器为 0  void increment() {  for (int i = 0; i < 100000; ++i) {  ++counter; // 原子递增操作  }  
}  int main() {  std::thread t1(increment);  std::thread t2(increment);  t1.join();  t2.join();  std::cout << "Final counter value: " << counter << std::endl; // 输出最终的计数器值  return 0;  
}

在这个示例中,两个线程都试图递增同一个计数器。由于 counter 是一个 std::atomic<int> 类型,因此这些递增操作是原子的,从而避免了数据竞争。最终,计数器的值将是 200000(假设没有其他并发问题)。

2.std::atomic 多种使用方式举例

std::atomic 是 C++ 中的一个模板类,它提供了原子操作,使得在多线程环境中对数据的访问是线程安全的。以下是 std::atomic 的一些常见使用方式的例子:

1. 基本操作

加载和存储值
#include <iostream>  
#include <atomic>  std::atomic<int> ai(0); // 初始化一个原子整数为 0  int main() {  int value = ai.load(); // 加载值  ai.store(42); // 存储值  std::cout << "Value loaded: " << value << std::endl;  std::cout << "Value stored: " << ai.load() << std::endl;  return 0;  
}
原子算术操作

#include <iostream>  
#include <atomic>  std::atomic<int> ai(0);  int main() {  ai += 10; // 原子加法  std::cout << "Value after increment: " << ai.load() << std::endl;  ai -= 5; // 原子减法  std::cout << "Value after decrement: " << ai.load() << std::endl;  return 0;  
}

2. 复合操作

compare_exchange_weak 和 compare_exchange_strong

这两个函数尝试用新值替换当前值,但仅当当前值等于期望值时才这样做。

#include <iostream>  
#include <atomic>  std::atomic<int> ai(0);  int main() {  int expected = 0;  bool result = ai.compare_exchange_strong(expected, 42); // 尝试替换为 42,如果当前值是 0  if (result) {  std::cout << "Value replaced successfully" << std::endl;  } else {  std::cout << "Value not replaced" << std::endl;  }  std::cout << "Final value: " << ai.load() << std::endl;  return 0;  
}

3. 使用 std::atomic 进行线程同步

以下是一个简单的例子,展示了如何使用 std::atomic 和 std::thread 进行线程同步。

#include <iostream>  
#include <thread>  
#include <atomic>  std::atomic<bool> ready(false);  
std::atomic<int> result(0);  void compute() {  // 模拟计算过程  for (int i = 0; i < 1000000; ++i) {  // ...  }  result.store(42); // 将结果存储在原子变量中  ready.store(true); // 设置 ready 标志为 true  
}  int main() {  std::thread t(compute);  // 等待 ready 标志变为 true  while (!ready.load()) {  // 等待,或者可以做一些其他工作  }  // 当 ready 为 true 时,可以安全地读取 result  std::cout << "Result: " << result.load() << std::endl;  t.join();  return 0;  
}

4. 使用 std::atomic 指针

你也可以使用 std::atomic 来存储和管理指针。这在某些情况下(如线程安全的智能指针)可能是有用的。

#include <iostream>  
#include <memory>  
#include <atomic>  
#include <thread>  std::atomic<std::shared_ptr<int>> ptr(nullptr);  void threadFunc() {  // 等待 ptr 被设置  while (!ptr.load()) {  // 等待,或者可以做一些其他工作  }  std::cout << "Value: " << *ptr.load() << std::endl;  
}  int main() {  std::shared_ptr<int> newPtr = std::make_shared<int>(42);  ptr.store(newPtr); // 设置原子指针  std::thread t(threadFunc);  t.join();  return 0;  
}

请注意,虽然 std::atomic 提供了基本的原子操作,但在复杂的并发编程场景中,可能还需要使用其他同步原语(如互斥锁、条件变量等)来确保逻辑的正确性。

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

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

相关文章

Linux 操作系统多路IO复用

1.多路IO复用 多路I/O复用是通过一种机制&#xff0c;可以监视多个描述符&#xff0c;一旦某个描述符就绪&#xff08;一般是读就绪或者写就绪&#xff09;&#xff0c;能够通知程序进行相应的读写操作。 这个机制能够通过select/poll/eroll等来使用。这些函数都可以同时监视多…

文件流-二进制文件(中北大学-程序设计基础(2))

目录 题目 源码 结果示例 题目 建立两个二进制磁盘文件f1.dat,f2.dat&#xff0c;编程实现以下工作&#xff1a; &#xff08;1&#xff09;将20个整数&#xff08;可在程序中初始化&#xff09;&#xff0c;分别存放到两个磁盘文件中&#xff0c;前10个放到f1.dat中&…

Linux下网络命令

目录 需求1-查看本机是否存在22端口解法1解法2解法3 需求2-查看其他主机是否存在22端口解法1解法2解法3 需求3-查看TCP连接解法1/2 需求4-统计80端口tcp连接次数解法 需求5-查看总体网络速度解法 需求6-查看进程流量解法 需求7-dns解法 需求8-traceroute到baidu解法 需求9-查看…

任务通知理论和使用

文章目录 一、任务通知是什么&#xff1f;1.1任务通知的优势1.2任务通知的限制1.3通知状态和通知值 二、任务通知的使用2.1任务通知使用_轻量级信号量2.2任务通知使用_轻量级队列2.3任务通知使用_轻量级事件组 一、任务通知是什么&#xff1f; 我们使用队列、信号量、事件组等…

浅析视频汇聚EasyCVR视频融合云平台在机场安防智能检测建设中的应用

一、背景 机场作为国家交通枢纽和对外开放的窗口&#xff0c;其安全运行直接关系到乘客的生命安全、国家形象以及社会经济稳定。随着全球航空业的快速发展和人们出行需求的持续增长&#xff0c;机场作为重要的交通枢纽&#xff0c;其客流量和货运量均呈现出快速增长的态势。然而…

HCIP的学习(16)

BGP的状态机 ​ OSPF的状态机是在描述整个协议的完整工作过程&#xff0c;而BGP的状态机仅描述的是对等体关系建立过程中的状态变化。-----因为BGP将邻居建立过程以及BGP路由收发过程完全隔离。 ​ IGP协议在启动后&#xff0c;需要通过network命令激活接口&#xff0c;从而使…

Python模块之Numpy(三)-- 数组的访问

Numpy对数组的操作十分高效&#xff0c;这主要源于其对索引的使用。数组索引的使用和列表&#xff08;list&#xff09;类似&#xff0c;索引都是从0开始&#xff0c;在访问或者批量引用时&#xff0c;遵循左闭右开的原则。 对于一维数组 import numpy as np arr np.arange(…

SD-WAN供应商选择指南

企业网络日益演变&#xff0c;尤其是跨国企业、出海电商和外贸企业&#xff0c;其网络需求变得愈发复杂多样。SD-WAN技术因此备受瞩目&#xff0c;成为连接分支机构和数据中心的关键解决方案。然而&#xff0c;市面上的SD-WAN供应商众多&#xff0c;如何选择适合的服务商成为了…

gitignore配置不生效记录

第一种可能性&#xff1a; 在你所有的文件都通过了git add . 命令的情况下&#xff0c;使用指令git rm -r --cached .进行缓存清除&#xff0c;完成之后&#xff0c;再次通过git add . 然后通过git status去看提交的文件都有哪些。 第二种可能性 如果上面的不行就是你添加的…

混合使用MFC与QT的深度技术分析

混合使用MFC与QT的深度技术分析 目录 混合使用MFC与QT的深度技术分析 一、引言 二、MFC与QT概述 三、混合使用场景分析 四、技术挑战与解决方案 五、实操&#xff1a;集成QT模块至MFC应用 六、性能考量与优化策略 七、安全性分析 八、案例研究 九、总结与未来展望 一、…

【机器学习】Scikit-Learn:Python机器学习的瑞士军刀

Scikit-Learn&#xff1a;Python机器学习的瑞士军刀 一、Scikit-Learn简介二、Scikit-Learn的核心功能数据预处理模型选择模型评估模型部署 三、Scikit-Learn的中文社区与API四、代码实例&#xff1a;使用Scikit-Learn进行鸢尾花数据集分类 在当今这个数据驱动的时代&#xff0…

C++ Primer 中文版(第 5 版)- 第四单元

第四单元 练习 4.1 编写一段程序&#xff0c;使用条件运算符从vector中找到哪些元素的值是奇数&#xff0c;然后将这些奇数值翻倍。 #include <iostream> #include <vector>using std::cout; using std::endl; using std::vector;int main() {vector<int>…

论文《Deep graph tensor learning for temporal link prediction》阅读

论文《Deep graph tensor learning for temporal link prediction》阅读 论文概况IntroductionRelated work动态图表示学习图张量表示 Preliminary张量生成建模 深度图张量学习模型A.基于图紧凑的空间表示B.时间模式表示C.时空特征聚合D.损失函数 实验数据集对比实验消融实验参…

美易官方:美国房地产贷款逾期率飙升,银行业危机仍可控?现货黄金暂守2360

美国房地产贷款逾期率飙升&#xff0c;银行业危机仍可控&#xff1f;现货黄金暂守2360 近年来&#xff0c;美国房地产市场一直处于波动之中&#xff0c;尤其是商业房地产领域。近期&#xff0c;美联储发出警告&#xff0c;称商业房地产贷款逾期率持续攀升&#xff0c;银行正在为…

鸿蒙ArkUI开发:常用布局【交叉轴】

交叉轴 垂直于主轴方向的轴线。Row容器交叉轴为纵向&#xff0c;Column容器交叉轴为横向。通过alignItems属性设置子元素在交叉轴&#xff08;排列方向的垂直方向&#xff09;上的对齐方式alignSelf属性用于控制单个子元素在容器交叉轴上的对齐方式&#xff0c;其优先级高于al…

M 有效算法

M 有效算法 本题考验二分知识&#xff0c;思路是二分k的取值&#xff0c;就按第一组样例来说当我们k取值为1的时候我们遍历数组想让|8-x|<k1的话x的取值范围是7-9&#xff0c;想让|3-x|<k2的话x的取值范围是1-5&#xff0c;两者x的区间不重合&#xff0c;说明肯定没有x能…

【力扣】164. 最大间距

164. 最大间距 题目描述 给定一个无序的数组 nums&#xff0c;返回 数组在排序之后&#xff0c;相邻元素之间最大的差值 。如果数组元素个数小于 2&#xff0c;则返回 0。 您必须编写一个在「线性时间」内运行并使用「线性额外空间」的算法。 示例 1: 输入: nums [3,6,9,…

几种ssh自动登录服务器的方法

一、Windows环境 1. 配置公钥和私钥 https://developer.aliyun.com/article/1132156 2. 使用putty.exe 官网见&#xff1a;https://www.putty.org/ 下载地址&#xff1a;https://www.chiark.greenend.org.uk/~sgtatham/putty/latest.html 使用示例如下&#xff1a; echo of…

BGP—边界网关协议

BGP 动态路由协议可以按照工作范围分为IGP以及EGP。IGP工作在同一个AS内&#xff0c;主要用来发现和计算路由&#xff0c;为AS内提供路由信息的交换&#xff1b;而EGP工作在AS与AS之间&#xff0c;在AS间提供无环路的路由信息交换&#xff0c;BGP则是EGP的一种。 BGP是一…

打开深度学习的锁:(0)什么是神经网络?有哪些必备的知识点准备?

PS&#xff1a;每每温故必而知新 什么是神经网络&#xff1f; 一、一个单神经元的神经网络二、多个单神经元的神经网络三、到底什么是机器学习&#xff1f;&#xff08;重点&#xff09;1&#xff1a;什么是机器学习的训练&#xff1f;2&#xff1a;什么是模型&#xff1f;权重…