C++之std::atomic类模板原子操作应用总结(二百三十九)

news2024/11/17 23:42:47

简介: CSDN博客专家,专注Android/Linux系统,分享多mic语音方案、音视频、编解码等技术,与大家一起成长!

优质专栏:Audio工程师进阶系列原创干货持续更新中……】🚀

人生格言: 人生从来没有捷径,只有行动才是治疗恐惧和懒惰的唯一良药.

更多原创,欢迎关注:Android系统攻城狮

欢迎关注Android系统攻城狮

1.前言

本篇目的:理解C++之std::atomic模板类函数load、store、exchange、increment、decrement、fetch_add、fetch_sub、fetch_and、fetch_or、fetch_xor用法。

std::atomic模板类作用

C++的std::atomic是一个模板类,用于实现原子操作。它提供了一种线程安全的方式来对共享数据进行操作,以避免竞态条件。

  1. 实现原子操作:std::atomic提供了一系列的成员函数,可用于对变量进行原子操作,包括读取、写入和修改。这些操作能够确保在多线程环境下,对共享数据的操作不会发生冲突或产生竞态条件。

  2. 线程同步:std::atomic提供了一种同步机制,用于保证多线程环境下的数据一致性。通过使用std::atomic的成员函数,可以实现不同线程间的同步操作,确保每个线程对共享数据的访问是有序的。

  3. 原子性操作:std::atomic操作是原子的,即不可中断的。当多个线程同时对同一个std::atomic对象进行操作时,操作会以原子的方式执行,不会出现数据不一致或异常的情况。

  4. 替代锁机制:在某些情况下,std::atomic可以替代传统的互斥锁机制。使用std::atomic进行原子操作,可以避免锁的开销和线程等待的问题,从而提高程序的性能。

std::atomic的作用是提供一种线程安全的方式来操作共享数据,保证数据的一致性和原子性,避免多线程环境下的竞态条件和冲突。它是C++多线程编程中常用的工具之一。

2.std::atomic模板类函数load、store、exchange、increment、decrement、fetch_add、fetch_sub、fetch_and、fetch_or、fetch_xor介绍

  1. std::atomic模板类的成员函数(load、store、exchange、increment、decrement、fetch_add、fetch_sub、fetch_and、fetch_or、fetch_xor)的实现原理是通过使用硬件级别的支持或者特殊的指令集来实现的。

  2. 在现代的计算机架构中,通常会提供原子操作的指令,例如比较交换指令(Compare-and-Swap)或交换指令(Exchange),这些指令可以保证对共享变量的操作是原子的,不会被其他线程的操作中断或交叉。

  3. std::atomic模板类的成员函数会使用这些硬件级别的原子指令来实现原子操作。具体的实现方式可能因不同的编译器、平台和架构而有所差异,但其基本原理是一致的。

  4. 这些原子操作的作用是为了在多线程环境中实现线程安全的操作。使用原子操作可以避免竞争条件(Race Condition)的问题,在多个线程同时对共享变量进行操作时,能够确保操作的原子性,保证数据的一致性和正确性。

  5. 原子操作可以应用于各种并发编程场景,例如引用计数、无锁数据结构、自旋锁、并行算法等。通过使用std::atomic模板类提供的原子操作函数,可以方便地在多线程环境中进行原子操作,避免了需要显式加锁的复杂性和开销。

  6. std::atomic模板类的成员函数的作用是实现线程安全的原子操作,利用硬件级别的支持或者特殊的指令集,保证对共享变量的操作是原子的,避免了竞争条件的问题。这些原子操作可以应用于各种并发编程场景,提供了一种简单、高效和可靠的线程安全机制。

3.应用实例

  1. load():

    • 描述:返回当前std::atomic对象的值。
    • 用法:T load(std::memory_order order = std::memory_order_seq_cst) const noexcept;
    • 示例:
    #include <atomic>
    
    int main() {
        std::atomic<int> num(42);
        int value = num.load();
        std::cout << "Value: " << value << std::endl;
        return 0;
    }
    
  2. exchange():

    • 描述:用给定的值替换std::atomic对象的值,并返回替换之前的值。
    • 用法:T exchange(T desired, std::memory_order order = std::memory_order_seq_cst) noexcept;
    • 示例:
    #include <atomic>
    
    int main() {
        std::atomic<int> num(42);
        int old_value = num.exchange(10);
        std::cout << "Old value: " << old_value << std::endl;
        std::cout << "New value: " << num.load() << std::endl;
        return 0;
    }
    
  3. increment():

    • 描述:将std::atomic对象的值递增1,并返回递增之前的值。
    • 用法:T increment(std::memory_order order = std::memory_order_seq_cst) noexcept;
    • 示例:
    #include <atomic>
    
    int main() {
        std::atomic<int> num(42);
        int old_value = num++;
        std::cout << "Old value: " << old_value << std::endl;
        std::cout << "New value: " << num.load() << std::endl;
        return 0;
    }
    
  4. decrement():

    • 描述:将std::atomic对象的值递减1,并返回递减之前的值。
    • 用法:T decrement(std::memory_order order = std::memory_order_seq_cst) noexcept;
    • 示例:
    #include <atomic>
    
    int main() {
        std::atomic<int> num(42);
        int old_value = num--;
        std::cout << "Old value: " << old_value << std::endl;
        std::cout << "New value: " << num.load() << std::endl;
        return 0;
    }
    
  5. fetch_add():

    • 描述:将给定的值加到std::atomic对象的值上,并返回加之前的值。
    • 用法:T fetch_add(T arg, std::memory_order order = std::memory_order_seq_cst) noexcept;
    • 示例:
    #include <atomic>
    
    int main() {
        std::atomic<int> num(42);
        int old_value = num.fetch_add(10);
        std::cout << "Old value: " << old_value << std::endl;
        std::cout << "New value: " << num.load() << std::endl;
        return 0;
    }
    
  6. fetch_sub():

    • 描述:将给定的值从std::atomic对象的值中减去,并返回减之前的值。
    • 用法:T fetch_sub(T arg, std::memory_order order = std::memory_order_seq_cst) noexcept;
    • 示例:
    #include <atomic>
    
    int main() {
        std::atomic<int> num(42);
        int old_value = num.fetch_sub(10);
        std::cout << "Old value: " << old_value << std::endl;
        std::cout << "New value: " << num.load() << std::endl;
        return 0;
    }
    
  7. fetch_and():

    • 描述:将std::atomic对象的值与给定的值进行按位与操作,并返回按位与之前的值。
    • 用法:T fetch_and(T arg, std::memory_order order = std::memory_order_seq_cst) noexcept;
    • 示例:
    #include <atomic>
    
    int main() {
        std::atomic<int> num(42);
        int old_value = num.fetch_and(10);
        std::cout << "Old value: " << old_value << std::endl;
        std::cout << "New value: " << num.load() << std::endl;
        return 0;
    }
    
    
  8. fetch_or():

    • 描述:将std::atomic对象的值与给定的值进行按位或操作,并返回按位或之前的值。
    • 用法:T fetch_or(T arg, std::memory_order order = std::memory_order_seq_cst) noexcept;
    • 示例:
    #include <atomic>
    
    int main() {
        std::atomic<int> num(42);
        int old_value = num.fetch_or(10);
        std::cout << "Old value: " << old_value << std::endl;
        std::cout << "New value: " << num.load() << std::endl;
        return 0;
    }
    
  9. fetch_xor():

    • 描述:将std::atomic对象的值与给定的值进行按位异或操作,并返回按位异或之前的值。
    • 用法:T fetch_xor(T arg, std::memory_order order = std::memory_order_seq_cst) noexcept;
    • 示例:
    #include <atomic>
    
    int main() {
        std::atomic<int> num(42);
        int old_value = num.fetch_xor(10);
        std::cout << "Old value: " << old_value << std::endl;
        std::cout << "New value: " << num.load() << std::endl;
        return 0;
    }
    

10.store()

  • 描述:std::atomic的store函数用于将给定的值存储到std::atomic对象中。
  • 用法:template void store(T value, std::memory_order order = std::memory_order_seq_cst) noexcept;
  • 示例:
#include <atomic>
#include <iostream>

int main() {
    std::atomic<int> value;

    // 使用store函数将给定的值存储到std::atomic对象中
    value.store(42);

    // 打印存储后的值
    std::cout << "Value: " << value.load() << std::endl;

    return 0;
}

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

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

相关文章

JAVA+SpringBoot+VUE工厂车间管理系统(含论文)源码

springboot169基于vue的工厂车间管理系统的设计录像(毕业设计jdz2023) 一、源码描述 JAVASpringBootVUE工厂车间管理系统,包含源码数据库论文等,含MySQL脚本&#xff0c;基于B/S和Web开发的&#xff0c;感兴趣的朋友可以下载看看 二、功能介绍 1、个人中心 2、人员管理 3、设备…

计算机图像处理:图像轮廓

图像轮廓 图像阈值分割主要是针对图片的背景和前景进行分离&#xff0c;而图像轮廓也是图像中非常重要的一个特征信息&#xff0c;通过对图像轮廓的操作&#xff0c;就能获取目标图像的大小、位置、方向等信息。画出图像轮廓的基本思路是&#xff1a;先用阈值分割划分为两类图…

Textpad 缺少Java编译和运行功能

一、问题 缺少Java编译和运行功能 二、处理方法 1、点击菜单Configure->Preferences 2、点击 Tools -> Add -> Java SDK Commands 3、点击应用和确认 三、结果

现代 GPU 容易受到新 GPU.zip 侧通道攻击

来自四所美国大学的研究人员开发了一种新的 GPU 侧通道攻击&#xff0c;该攻击利用数据压缩在访问网页时泄露现代显卡中的敏感视觉数据。 研究人员通过 Chrome 浏览器执行跨源 SVG 过滤器像素窃取攻击&#xff0c;证明了这种“ GPU.zip ”攻击的有效性。 研究人员于 2023 年 …

【JVM】第五篇 垃圾收集器G1和ZGC详解

导航 一. G1垃圾收集算法详解1. 大对象Humongous说明2. G1收集器执行一次GC运行的过程步骤3. G1垃圾收集分类4. G1垃圾收集器参数设置5. G1垃圾收集器的优化建议6. 适合使用G1垃圾收集器的场景?二. ZGC垃圾收集器详解1. NUMA与UMA2. 颜色指针3. ZGC的运作过程4. ZGC垃圾收集器…

mysql面试题2:说一说MySQL的架构设计?一条 MySQL 语句执行的步骤?

该文章专注于面试,面试只要回答关键点即可,不需要对框架有非常深入的回答,如果你想应付面试,是足够了,抓住关键点 面试官:说一说MySQL的架构设计? MySQL的架构设计主要包括以下几个组件: 连接器(Connector):负责与客户端建立连接,并进行身份验证和授权。 查询缓存…

文件的随机读写函数:fseek

目录 函数介绍&#xff1a; fseek&#xff1a; 原型&#xff1a; 参数说明&#xff1a; int origin&#xff1a; 举例&#xff1a; 文件内容展示&#xff1a; 正常的使用fgetc函数&#xff1a; 结果&#xff1a; 使用了fseek之后&#xff1a; SEEK_SET :从开始位置进行…

VBA技术资料MF60:从二维变体数组中删除一列数据

【分享成果&#xff0c;随喜正能量】如果一个人能看破红尘&#xff0c;特别是如果能看破贪欲的本质&#xff0c;他的身心一定会非常自在&#xff0c;外在的气色会很好&#xff0c;内心也会非常安乐。如果一个人总是贪执某人&#xff0c;那他的戒律肯定不会清净&#xff0c;他的…

渗透测试之打点

请遵守中华人民共和国网络安全法 打点的目的是获取一个服务器的控制权限 1. 企业架构收集 &#xff08;1&#xff09;官网 &#xff08;2&#xff09;网站或下属的子网站&#xff0c;依次往下 天眼查 企查查 2. ICP 备案查询 ICP/IP地址/域名信息备案管理系统 使用网站…

轮廓检测及透视变换

文章目录 注&#xff1a;代码来自b站&#xff1a;阿头目G # 导入工具包 import numpy as np import argparse import cv2# # 设置参数 # ap argparse.ArgumentParser() # ap.add_argument("-i", "--image", required True, # help "Path to the i…

flutter GetMaterialAPP unknownRoute 失效

这个问题。。。找了半天&#xff0c;最后去了 官网的ISSu找到了答案&#xff0c;分享给同样困惑的小伙伴们 为了让unknownRoute能成功工作, 你的initialRoute一定不能是/, 否则当有未定义的导航时, Get只会跳到initialRoute页面去了. GetPage 里面不要把root设置为“/” 页面&a…

支付宝支付模块开发

生成二维码 使用Hutool工具类生成二维码 引入对应的依赖 <dependency><groupId>cn.hutool</groupId><artifactId>hutool-all</artifactId><version>5.7.5</version> </dependency><dependency><groupId>com.go…

Oracle表锁了怎么办?

最近同事在开发过程中&#xff0c;由于网络或电脑卡顿导致PLSQL执行 update 语句操作一直无响应。随后同事就将PLSQL关闭重新打开再次执行 update 语句。来来回回操作了多次。最终导致了表被锁定。 解决问题 1、查看锁表情况 ---1、查看那些表被锁住 select b.owner, b.objec…

学之思项目第一天-完成项目搭建

一、前端 拉下前端代码执行 npm i 然后执行npm run serve就行了 二、后端 搭建父子模块 因为这个涉及到前台以及后台管理所以使用父子模块 并且放置一个公共模块&#xff0c;放置公共的依赖以及公共的代码 2.1 搭建父子工程 这个可以使用直接一个个的maven模块&#xff…

【网络协议】UDP

UDP协议与TCP协议都是传输层协议&#xff0c;应用层把数据拷贝到传输层&#xff0c;后续动作由下层自行决定。 UDP协议端格式 16位 UDP 长度 , 表示整个数据报 (UDP 首部 UDP 数据 ) 的最大长度 ;&#xff08;也就是65535字节&#xff09; 如果校验和出错 , 就会直接丢弃 ; …

湖南软件测评公司简析:软件功能测试和非功能测试的联系和区别

一、软件功能测试   软件功能测试旨在验证软件是否按照需求规格说明书的要求正常工作。具体而言&#xff0c;功能测试会对软件的所有功能进行测试&#xff0c;以确保其满足用户的需求和预期。在进行功能测试时&#xff0c;根据需求规格说明书编写测试用例&#xff0c;并在测试…

初识Java 11-1 函数式编程

目录 旧方式与新方式 lambda表达式 方法引用 Runnable 未绑定方法引用 构造器方法引用 函数式接口 带有更多参数的函数式接口 解决缺乏基本类型函数式接口的问题 本笔记参考自&#xff1a; 《On Java 中文版》 函数式编程语言的一个特点就是其处理代码片段的简易性&am…

从零开始之了解电机及其控制(10)空间矢量理论

与一维数字转子位置不同&#xff0c;电流和电压都是二维的。可以在矩形笛卡尔平面中考虑这些尺寸。 用旋转角度和幅度来描述向量 虽然电流命令的幅度和施加的电压是进入控制器的误差项的函数&#xff0c;它们施加的角度是 d-q 轴方向的函数&#xff0c;因此也是转子位置的函数。…

目标追踪学习经验总结

标题目标追踪算法学习经验总结   最近对目标追踪算法进行了学习&#xff0c;以下是我的学习经验&#xff0c;如有不对之处&#xff0c;欢迎大家指正。 1、简介 1.1 定义 目标跟踪是通过分析视频图片序列&#xff0c;对检测出的各个候选目标区域实施匹配&#xff0c;定位出这…

架构设计师

一、软件架构 .特定领域软件架构(Domain Specific Software Architecture,DSSA) &#xff08;1&#xff09;垂直域。定义了一个特定的系统族,导出在该领域中可作为系统的可行解决方案的一个通用软件架构。 &#xff08;2&#xff09;水平域。定义了在多个系统和多个系统族中功…