【C++并发编程】(五)原子操作

文章目录

  • (五)原子操作
    • C++中的原子操作
    • 内存顺序
    • 原子操作解决数据竞争问题

(五)原子操作

原子操作(Atomic Operations)是一种在并发编程中用于防止数据竞争和保证线程安全性的机制。原子操作是不可中断的操作,一旦开始,就必须完全执行完毕,不受其他线程干扰,可以确保多个线程在访问和修改共享数据时不会发生冲突,从而避免了数据竞争和相关的并发问题。

std::atomic是C++11标准库引入的一个模板类,它提供了对基本数据类型(如int、bool、float,指针等)的原子操作支持。

C++中的原子操作

在C++中,std::atomic类型提供了一系列操作保证了操作的原子性,即操作在执行过程中不会被其他线程打断。

  1. 构造和赋值
  • 构造函数:可以用初始值构造std::atomic对象。
  • 赋值操作符:= 可以用于给std::atomic对象赋值,但这不是原子操作。
  1. 存储和加载
  • store(T desr, std::memory_order order = std::memory_order_seq_cst):原子地将指定的值存储到原子对象中。
  • load(std::memory_order order = std::memory_order_seq_cst) const:原子地从原子对象中加载值。
  1. 算术操作
  • 对于整数类型的std::atomic,提供了 ++--+=-=*=/=&=|=^= 等算术操作符的重载,它们都是原子的。
  • fetch_add(T arg, std::memory_order order = std::memory_order_seq_cst): 原子地增加arg
  • fetch_sub(T arg, std::memory_order order = std::memory_order_seq_cst) : 原子地减少arg
  1. 比较并交换
  • compare_exchange_weak(T& expected, T desired, std::memory_order success = std::memory_order_seq_cst, std::memory_order failure = std::memory_order_seq_cst)
  • compare_exchange_strong(T& expected, T desired, std::memory_order success = std::memory_order_seq_cst, std::memory_order failure = std::memory_order_seq_cst)

这两个函数尝试用desired替换当前值,但仅当当前值等于expected时才这样做。如果替换成功,expected将被更新为新的值。

两者的主要区别在于 compare_exchange_weak 可能会在期望值和当前值匹配时因伪失败而返回 false,而 compare_exchange_strong 则保证在匹配时一定返回 true 并执行交换。

伪失败指的是某些操作在逻辑上应该成功但由于某些原因(如硬件或操作系统的优化)而未能成功。

  1. 交换
  • exchange(T desired, std::memory_order order = std::memory_order_seq_cst):原子地将desired与当前值交换,并返回旧值。
  1. 位操作
  • 对于整数类型的std::atomic,也提供了位操作符的重载,如&=|=^=等。
  1. 非成员函数
  • std::atomic_flag 是一个特殊的原子类型,它只提供了一个操作:test_and_set,用于实现自旋锁等低级同步原语。

内存顺序

上述许多操作都接受一个std::memory_order参数来指定内存顺序(Memory Order)。内存顺序决定了两个或多个内存访问操作之间的相对顺序。在多线程环境中,由于处理器缓存、指令重排和编译器优化等因素,内存访问的顺序可能并不总是按照代码中的顺序执行。这可能导致数据竞争(data race)和未定义行为(undefined behavior)。在C++11及以后的版本中,std::atomicstd::memory_order一起提供了对内存顺序的细粒度控制。
std::memory_order 枚举类型定义了不同的内存顺序约束,这些约束用于控制编译器和处理器对内存操作的重新排序。不同的内存顺序约束有不同的性能和正确性保证。常见的内存顺序包括:

  • std::memory_order_relaxed:最宽松的约束,不保证任何特定的内存顺序。适用于不需要同步或顺序保证的原子操作,如统计计数器的增加。
  • std::memory_order_consume:主要应用于消费者-生产者模型中的依赖关系同步,确保依赖于原子操作结果的后续操作能按正确顺序执行。
  • std::memory_order_acquire:在读取原子变量之前使用,确保之前的所有读取和写入操作对当前线程可见,常用于读-写锁(read-write lock)的读操作。
  • std::memory_order_release:在写入原子变量之后使用,确保之后的所有读取和写入操作对其他线程可见,常用于写-写锁(write-write lock)的写操作或发布新值到共享变量。
  • std::memory_order_acq_rel:结合了acquirerelease的语义,常用于保护一段代码(critical section)的起始和结束,确保只有单一线程能执行这段代码。
  • std::memory_order_seq_cst:提供最强的顺序一致性保证,保证所有线程看到的操作顺序都是一致的,就像单线程执行一样。适用于需要严格顺序保证的场景。

原子操作解决数据竞争问题

【C++并发编程】(三)互斥锁:std::mutex 使用互斥锁解决的数据竞争问题,原子操作也可以解决。下面给出一个例子:

#include <iostream>  
#include <thread>  

  
std::atomic<int> counter(0); // 定义一个原子整数counter
  
void increment() {  
    for (int i = 0; i < 100000; ++i) {  
   		++counter; // 原子自增操作
    }  
}  
  
int main() {  
    std::thread th1(increment);  
    std::thread th2(increment);  
  
    th1.join();  
    th2.join();  

    std::cout << "Final counter value: " << counter << std::endl;  
    // Final counter value: 200000
    
    return 0;  
}

由于counterstd::atomic类型的,所以++counter操作是原子的,即使在多线程环境下也不会产生数据竞争。

原子操作与互斥锁

原子操作通常比互斥锁具有更高的性能,但原子操作通常针对单个数据项(如一个整数或指针)进行,它们确保了对该数据项的访问是原子的,即不会被其他线程打断。互斥锁则通常用于保护一个代码块或整个数据结构,确保在该代码块或数据结构被访问时,只有一个线程能够执行。因此,在选择使用原子操作还是互斥锁时,需要根据具体的应用场景和需求进行权衡。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

js api part3

环境对象 环境对象&#xff1a; 指的是函数内部特殊的 变量 this &#xff0c; 它代表着当前函数运行时所处的环境 作用&#xff1a; 弄清楚this的指向&#xff0c;可以让我们代码更简洁 函数的调用方式不同&#xff0c;this 指代的对象也不同 【谁调用&#xff0c; this 就是…

springboot模块以及非springboot模块构成的多模块maven项目最佳构建方式

文章目录 背景一般的实现使用spring-boot-dependencies 更优雅的实现. 背景 有时候构建一个多模块maven项目其中某一个模块是web-service需要使用spring boot,其他模块跟spring boot 完全无关,本文总结一下在这个场景下maven项目最佳构建方式. 一般的实现 网上应该也看到过很…

智能工业相机哪家好?

一、什么是智能工业相机 在工业自动化的浪潮中&#xff0c;智能工业相机扮演着至关重要的角色。它们如同工业领域的“眼睛”&#xff0c;为生产过程提供精准的视觉监测和数据采集。然而&#xff0c;面对众多的智能工业相机品牌&#xff0c;如何选择一款真正适合的产品成为了众多…

企业开发基础--数据库

今天完成了数据库学习的全部内容&#xff0c;在事务&#xff0c;索引&#xff0c;范式中要有个人逻辑上的理解&#xff0c;也算是卡着点完成了大多数预期&#xff0c;还有一个Java游戏未完成&#xff0c;会后续补上。 之后的一周要完成34道数据库练习题以及JDBC&#xff0c;学…

88、动态规划-乘积最大子数组

思路&#xff1a; 首先使用递归来解&#xff0c;从0开始到N&#xff0c;每次都从index开始到N的求出最大值。然后再次递归index1到N的最大值&#xff0c;再求max。代码如下&#xff1a; // 方法一&#xff1a;使用递归方式找出最大乘积public static int maxProduct(int[] num…

Graph RAG:基于知识图谱的检索增强技术与优势对比

身处信息爆炸时代&#xff0c;如何从海量信息中获取准确全面的搜索结果&#xff0c;并以更直观、可读的方式呈现出来是大家期待达成的目标。传统的搜索增强技术受限于训练文本数量、质量等问题&#xff0c;对于复杂或多义词查询效果不佳&#xff0c;更无法满足 ChatGPT 等大语言…

【Linux】进程间通信 - 管道

文章目录 1. 进程间通信介绍1.1 进程间通信目的1.2 进程间通信发展1.3 进程间通信分类 2. 管道2.1 什么是管道2.2 匿名管道2.3 用 fork 来共享管道原理2.4 站在文件描述符角度 - 深入理解管道2.5 站在内核角度 - 管道本质2.6 管道读写规则2.7 管道特点 3. 命名管道3.1 匿名管道…

C语言实战项目--贪吃蛇

贪吃蛇是久负盛名的游戏之一&#xff0c;它也和俄罗斯⽅块&#xff0c;扫雷等游戏位列经典游戏的行列。在编程语言的教学中&#xff0c;我们以贪吃蛇为例&#xff0c;从设计到代码实现来提升大家的编程能⼒和逻辑能⼒。 在本篇讲解中&#xff0c;我们会看到很多陌生的知识&…

牛角源码 | 【独立版】商城盲盒源码带uniapp(H5+小程序+APP三端)全开源

前端uniapp开源代码&#xff0c;可用HBuilder工具无限发行H5、小程序和打包app&#xff0c;后端PHP开源源码&#xff0c;支持二开。 内有安装搭建教程&#xff0c;轻松部署&#xff0c;搭建即可运营&#xff0c;内置永久免费更新地址&#xff0c;后续无忧升级。 下载地址&…

window 安装ai 基础环境(yolo8,训练推理等)

安装步骤: 1. python sdk 3.9以上&#xff1a;选择 3.9.13, 不知道为什么 3.9.0-0a等安装pytorch 不行。 2. 显卡驱动 可以使用驱动精灵 直接安装N 卡推荐 3. 安装机器学习套件CUDA cuda 安装在PyTorch 需要根 PyTorch版本一致&#xff0c;我的 win-srv 最高支持 12.1 …

专业渗透测试 Phpsploit-Framework(PSF)框架软件小白入门教程(五)

本系列课程&#xff0c;将重点讲解Phpsploit-Framework框架软件的基础使用&#xff01; 本文章仅提供学习&#xff0c;切勿将其用于不法手段&#xff01; 继续接上一篇文章内容&#xff0c;讲述如何进行Phpsploit-Framework软件的基础使用和二次开发。 在下面的图片中&#…

星辰考古:TiDB v1.0 再回首

“ 1.0 版本只是个开始&#xff0c;是新的起点&#xff0c;愿我们一路相扶&#xff0c;不负远途。 前言 TiDB 是 PingCAP 公司自主设计、研发的开源分布式关系型数据库。 近日&#xff0c;TiDB v8.0.0 DMR 发布&#xff0c;详细发版说明戳这里&#xff1a; https://docs.pingca…

2024年Q1季度防晒霜数据分析:个性化与差异化成为破局关键

五一出游期间&#xff0c;防晒必不可少&#xff0c;尤其是随着“颜值经济”的崛起&#xff0c;防晒霜成为了许多消费者出游时的必备选择。但随着“物理防晒”、“硬防晒”等概念的推出&#xff0c;防晒霜作为“化学防晒”的代表&#xff0c;在今年Q1季度线上市场表现受到影响。…

ICode国际青少年编程竞赛- Python-1级训练场-变量入门

ICode国际青少年编程竞赛- Python-1级训练场-变量入门 1、 a 4 Dev.turnRight() Dev.step(a)2、 a 4 Spaceship.step(a) Dev.step(a)3、 a 4 Dev.step(a) Dev.turnLeft() Dev.step(a)4、 a 5 Dev.step(a) Spaceship.step(a) Dev.step(a)5、 a 3 Dev.step(a) Dev.tur…

轨道交通巡检机器人的应用范围

在现代轨道交通系统的庞大网络中&#xff0c;无数的轨道、设备和设施交织在一起&#xff0c;如同一个精密的机器在高效运转。而在这背后&#xff0c;轨道交通巡检机器人正悄然登场&#xff0c;它们如同一个个智能的守护者&#xff0c;穿梭于各个场景之中。那么&#xff0c;这些…

【LeetCode:1235. 规划兼职工作 + 动态规划 + 二分查找】

&#x1f680; 算法题 &#x1f680; &#x1f332; 算法刷题专栏 | 面试必备算法 | 面试高频算法 &#x1f340; &#x1f332; 越难的东西,越要努力坚持&#xff0c;因为它具有很高的价值&#xff0c;算法就是这样✨ &#x1f332; 作者简介&#xff1a;硕风和炜&#xff0c;…

win10安装DHCP服务--用于2台机器之间搭建简易网络来进入目标机器修改配置

前言&#xff1a; 客户多了&#xff0c;往往会出现各种突发情况。 比如一个客户现场没有DHCP&#xff0c;没有显示器&#xff0c;键盘。 你只有一台笔记本的情况下要配置目标机器的网络。要如何配置&#xff1f;&#xff1f; 这时候就可以使用这篇博客提供的方式了。 Windows…

Android使用kts发布aar到JitPack仓库

Android使用kts发布aar到JitPack 之前做过sdk开发&#xff0c;需要将仓库上传到maven、JitPack或JCenter,但是JCenter已停止维护&#xff0c;本文是讲解上传到JitPack的方式,使用KTS语法&#xff0c;记录使用过程中遇到的一些坑.相信Groovy的方式是大家经常使用的&#xff0c;…

Codeforces Round 738 (Div. 2) D2. Mocha and Diana (Hard Version)

题目 思路&#xff1a; 性质1&#xff1a;能在结点u&#xff0c;v添加边的充要条件是u&#xff0c;v在第一个图和第二个图都不连通 性质2&#xff1a;可以添加的边数等于 n - 1 - max(m1, m2)&#xff0c;并且添加边的顺序不会影响结果&#xff08;即 边&#xff08;u&#x…

U.S. Student Information Center——全球学历认证

权威机构 中国留服中心认证&#xff0c;全称是中国教育部留学服务中心国(境)外学历学位认证。国&#xff08;境&#xff09;外学历学位认证工作旨在落实中华人民共和国的留学政策&#xff0c;即中国教育部留学服务中心根据归国留学生提出的申请&#xff0c;鉴别国(境)外学历的…
最新文章