当前位置: 首页 > news >正文

2022-09-01 C++并发编程(十七)

C++并发编程(十七)

  • 前言
  • 一、操作std::atomic<Ptr*>类对象
  • 总结


前言

std::atomic<Ptr*> 是原子指针类,除了和原子布尔类相同的成员函数,还有更多的计算相关函数,如果对前两篇文章完全掌握,此篇文章的内容不难掌握。


一、操作std::atomic<Ptr*>类对象

与原子布尔类一样,原子指针类可用普通的类型指针进行初始化:

    char charArr[] = "abcd";

    //初始化原子指针
    std::atomic<char *> atomicPtr(charArr);

判断是否无锁结构:

    //原子指针是否是无锁结构
    std::cout << atomicPtr.is_lock_free() << std::endl;

原子指针值的读取与写入:

    //读取原子指针值,可用读操作的内存次序
    auto charPtr = atomicPtr.load();

    char charArr2[] = "efgh";

    //写入原子指针,可用写操作的内存次序
    atomicPtr.store(charArr2);

原子指针值的交换更新:

    //更新原子指针,返回原值,读改写内存次序
    charPtr = atomicPtr.exchange(charArr);

原子指针值的 “比较交换更新”:

    char *charPtr2 = charArr2;

    char charArr3[] = "ijkl";

    //第一个参数必须是指针,不能是数组,因参数是引用,不会退化成指针
    //依然是两个内存操作次序,与期望指针值一致,则是读改写次序,否则是读次序
    while (!atomicPtr.compare_exchange_weak(charPtr2, charArr3))
    {
    }
    //同 weak 版本,第一个参数必须是指针
    //依然是两个内存操作次序
    atomicPtr.compare_exchange_strong(charPtr2, charArr);

原子指针增加了算数函数,

后移 fetch_add(ptrdiff_t __op, std::memory_order __m = memory_order_seq_cst)

前移fetch_sub(ptrdiff_t __op, std::memory_order __m = memory_order_seq_cst)

其语义是返回原值,指针前后移动若干,可按照 “读改写” 操作设置内存顺序。

    //返回指针原值,原子指针向后移动一个,读改写操作,可用任何内存次序
    charPtr = atomicPtr.fetch_add(1);

    //返回指针原值,原子指针向前移动一个,读改写操作,可用任何内存次序
    charPtr = atomicPtr.fetch_sub(1);

原子指针类还有自增 “++”,自减 “–” 操作,和普通指针运算操作无异,因原子指针类不支持拷贝赋值,只会返回普通指针,并且不可设置内存次序。

    //原子指针向后移动一个,并返回更新的值,不可设定内存次序,服从std::memory_order_seq_cst
    charPtr = ++atomicPtr;

    //原子指针向前移动一个,并返回更新的值,不可设定内存次序,服从std::memory_order_seq_cst
    charPtr = --atomicPtr;

    //返回指针原值,原子指针后移一个,不可设定内存次序,服从std::memory_order_seq_cst
    charPtr = atomicPtr++;

    //返回指针原值,原子指针前移一个,不可设定内存次序,服从std::memory_order_seq_cst
    charPtr = atomicPtr--;

    //原子指针像后移动一个,不可设定内存次序,服从std::memory_order_seq_cst
    atomicPtr += 1;

    //原子指针向前移动一个,不可设定内存次序,服从std::memory_order_seq_cst
    atomicPtr -= 1;

以下是全部示例代码,可一边 debug 一边熟悉其操作。

#include <atomic>
#include <iostream>

auto main() -> int
{
    char charArr[] = "abcd";

    //初始化原子指针
    std::atomic<char *> atomicPtr(charArr);

    //原子指针是否是无锁结构
    std::cout << atomicPtr.is_lock_free() << std::endl;

    //读取原子指针值,可用读操作的内存次序
    auto charPtr = atomicPtr.load();

    char charArr2[] = "efgh";

    //写入原子指针,可用写操作的内存次序
    atomicPtr.store(charArr2);

    //更新原子指针,返回原值,读改写内存次序
    charPtr = atomicPtr.exchange(charArr);

    char *charPtr2 = charArr2;

    char charArr3[] = "ijkl";

    //第一个参数必须是指针,不能是数组,因参数是引用,不会退化成指针
    //依然是两个内存操作次序
    while (!atomicPtr.compare_exchange_weak(charPtr2, charArr3))
    {
    }
    //同 weak 版本,第一个参数必须是指针
    //依然是两个内存操作次序
    atomicPtr.compare_exchange_strong(charPtr2, charArr);

    //返回指针原值,原子指针向后移动一个,读改写操作,可用任何内存次序
    charPtr = atomicPtr.fetch_add(1);

    //返回指针原值,原子指针向前移动一个,读改写操作,可用任何内存次序
    charPtr = atomicPtr.fetch_sub(1);

    //原子指针向后移动一个,并返回更新的值,不可设定内存次序,服从std::memory_order_seq_cst
    charPtr = ++atomicPtr;

    //原子指针向前移动一个,并返回更新的值,不可设定内存次序,服从std::memory_order_seq_cst
    charPtr = --atomicPtr;

    //返回指针原值,原子指针后移一个,不可设定内存次序,服从std::memory_order_seq_cst
    charPtr = atomicPtr++;

    //返回指针原值,原子指针前移一个,不可设定内存次序,服从std::memory_order_seq_cst
    charPtr = atomicPtr--;

    //原子指针像后移动一个,不可设定内存次序,服从std::memory_order_seq_cst
    atomicPtr += 1;

    //原子指针向前移动一个,不可设定内存次序,服从std::memory_order_seq_cst
    atomicPtr -= 1;

    return 0;
}

总结

原子指针类相较原子布尔类,增加了一些运算操作,及重载运算符,不难理解,多用即会。

相关文章:

  • 一次性安装所有的包、卸载包
  • 航拍倾斜摄影 Web 3D GIS 数字孪生智慧火电厂
  • 迅为RK3568开发板Linux_NVR_SDK系统开发-查看NPU/GPU/CPU频率使用率
  • CentOS 安装 rabbitMQ
  • springboot毕设项目疫情下药店管理系统xcu0u(java+VUE+Mybatis+Maven+Mysql)
  • 云原生游戏第 2 讲:OpenKruiseGame 设计理念详解
  • 模型压缩- 剪枝/量化/蒸馏/AutoML
  • 键值对RDD数据自定义分区_大数据培训
  • 详解小波变换在图像分解中的应用
  • Machine learning week 9(Andrew Ng)
  • 根据CI模式弄的一个python3访问MySql数据库的class
  • zabbix-server.service自启动服务配置文件
  • 免费GPU:九天•毕昇平台使用教程
  • centos7 安装apr1.7
  • centos linux 和 centos stream 的区别
  • SegmentFault for Android 3.0 发布
  • [译]Python中的类属性与实例属性的区别
  • 【React系列】如何构建React应用程序
  • 2019年如何成为全栈工程师?
  • CSS盒模型深入
  • Linux下的乱码问题
  • Spring Cloud(3) - 服务治理: Spring Cloud Eureka
  • Vue ES6 Jade Scss Webpack Gulp
  • 记一次删除Git记录中的大文件的过程
  • 线上 python http server profile 实践
  • 小程序01:wepy框架整合iview webapp UI
  • 小程序开发中的那些坑
  • 硬币翻转问题,区间操作
  • d²y/dx²; 偏导数问题 请问f1 f2是什么意思
  • AI算硅基生命吗,为什么?
  • NLPIR智能语义技术让大数据挖掘更简单
  • 完善智慧办公建设,小熊U租获京东数千万元A+轮融资 ...
  • ​ssh免密码登录设置及问题总结
  • # 深度解析 Socket 与 WebSocket:原理、区别与应用
  • #HarmonyOS:软件安装window和mac预览Hello World
  • (145)光线追踪距离场柔和阴影
  • (转)创业家杂志:UCWEB天使第一步
  • (转)项目管理杂谈-我所期望的新人
  • .NET Remoting Basic(10)-创建不同宿主的客户端与服务器端
  • .NET/C# 利用 Walterlv.WeakEvents 高性能地中转一个自定义的弱事件(可让任意 CLR 事件成为弱事件)
  • .NET/C# 使用 #if 和 Conditional 特性来按条件编译代码的不同原理和适用场景
  • .NET中GET与SET的用法
  • //解决validator验证插件多个name相同只验证第一的问题
  • /dev/sda2 is mounted; will not make a filesystem here!
  • @serverendpoint注解_SpringBoot 使用WebSocket打造在线聊天室(基于注解)
  • @synthesize和@dynamic分别有什么作用?
  • @在php中起什么作用?
  • [145] 二叉树的后序遍历 js
  • [2016.7 test.5] T1
  • [AHOI2009]中国象棋 DP,递推,组合数
  • [BZOJ 1032][JSOI2007]祖码Zuma(区间Dp)
  • [C#]扩展方法
  • [C#]手把手教你打造Socket的TCP通讯连接(一)
  • [codevs 1288] 埃及分数 [IDdfs 迭代加深搜索 ]
  • [Go WebSocket] 多房间的聊天室(三)自动清理无人房间