C++ 多线程编程(四) 原子类型atomic

news2024/10/7 9:24:45

C++ 11增加了原子类型atomic类,在一定条件下可以实现无锁编程。

1. 简介

atomic是一个模板类,定义如下:

template< class T >  struct atomic;

atomic可以实现无锁编程,在效率上要比mutex高很多,直接看个直观的例子:

#include <atomic>
#include <thread>
#include <iostream>
#include <mutex>
#include <vector>

int sum1{0};
std::atomic<int> sum2{0};
std::mutex mtx;
const int max_ = 100000000;

void add1()
{
    while (1) {
        mtx.lock();
        if (sum1 >= max_)
        {
            mtx.unlock();
            return;
        }
        sum1++;
        mtx.unlock();
    }
}

void add2()
{
    while (1)
    {
        if (sum2 >= max_) return;
        sum2++;
    }
}

int main()
{
    {
        std::vector<std::thread> ths;
        std::cout << "begin, sum1=" << sum1 << std::endl;
        auto start = std::chrono::system_clock::now();
        for (int i = 0; i <= 10; i++)
        {
            std::thread th{add1};
            ths.push_back(std::move(th));
        }
        for (int i = 0; i <= 10; i++)
        {
            ths[i].join();
        }
        auto finish = std::chrono::system_clock::now();
        auto cost = std::chrono::duration_cast<std::chrono::milliseconds>(finish-start);
        std::cout << "completed, sum1=" << sum1 << std::endl;
        std::cout << "mutex cost: " << (double)cost.count() << "ms" << std::endl;
    }
    std::cout << std::endl;
    {
        std::vector<std::thread> ths;
        std::cout << "begin, sum2=" << sum2 << std::endl;
        auto start = std::chrono::system_clock::now();
        for (int i = 0; i <= 10; i++)
        {
            std::thread th{add2};
            ths.push_back(std::move(th));
        }
        for (int i = 0; i <= 10; i++)
        {
            ths[i].join();
        }
        auto finish = std::chrono::system_clock::now();
        auto cost = std::chrono::duration_cast<std::chrono::milliseconds>(finish-start);
        std::cout << "completed, sum2=" << sum2 << std::endl;
        std::cout << "atomic cost: " << (double)cost.count() << "ms" << std::endl;
    }
}

这个例子里边,用多线程对一个变量自增,自增到一个值后结束,比较加锁和原子类型的运行时间,结果如下:

经多次测试,这个示例中atomic的效率是mutex的3~4倍。

2. 接口用法

下面记录的是atomic类的常用接口,全部接口在这里看

2.1 构造函数

atomic() noexcept = default;

constexpr atomic(T desired) noexcept;  //常用

atomic(const atomic&) = delete;  //禁用拷贝构造函数

 示例:

std::atomic<int> sum1{0};
std::atomic<int> sum2(1);
std::atomic<int> sum3 = 3;  //error, 禁止拷贝

2.2 修改、访问

atomic对象的修改主要使用store函数,访问主要使用load函数。

void store(T desired, std::memory_order order = std::memory_order_seq_cst) noexcept;

T load(std::memory_order order = std::memory_order_seq_cst) const noexcept;

std::memory_order是内存顺序,太复杂了,摆烂了,默认值又不是不能用!这篇勉强能看懂...

#include <atomic>
#include <iostream>

int main()
{
    std::atomic<int> a{1};
    std::cout << a.load() << std::endl;
    a.store(4);
    std::cout << a.load() << std::endl;
}
输出:
1
4

2.3 fetch_* 系列函数

fetch_ 开头的函数一共有5个,功能是简单的加减与之类的运算。与fetch_ 系列函数对应的运算符同样是5个,他们的功能是一样的。

fetch_*对应运算符功能
fetch_add+=原子地将参数加到存储于原子对象的值,并返回先前保有的值
fetch_sub-=原子地从存储于原子对象的值减去参数,并获得先前保有的值
fetch_and&=原子地进行参数和原子对象的值的逐位与,并获得先前保有的值
fetch_or|=原子地进行参数和原子对象的值的逐位或,并获得先前保有的值
fetch_xor^=原子地进行参数和原子对象的值的逐位异或,并获得先前保有的值
#include <atomic>
#include <iostream>

int main()
{
    std::atomic<int> a{1};
    std::cout << a.load() << std::endl;
    a.fetch_add(5);
    std::cout << a.load() << std::endl;
}
输出:
1
6

2.4 其他接口

2.4.1  is_lock_free

bool is_lock_free() const noexcept;

检查此类型所有对象上的原子操作是否免锁。

如果免锁,返回true,如果不是,会编译不过,这里是挺奇怪的。经过测试,模板类型的大小为1、2、4、8字节时,atomic是免锁的,其他情况都会编译不过,详情。

2.4.2  exchange

T exchange( T desired, std::memory_order order = std::memory_order_seq_cst ) noexcept;

原子地以 desired 替换底层值。操作为读-修改-写操作。

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

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

相关文章

有道云笔记常用快捷键

F5 同步/刷新 Shift AltD 插入当前时间&#xff1a; CTRL B 加粗 CTRL I 斜体字 CTRL U 下划线 CTRL E 删除线 CTRL D 任务框 CTRL 1 变成标题1 CTRL 2 变成标题2 CTRL 3 变成标题3 CTRL 4 变成标题4 CTRL G 高亮块 CTRL H 加水平线 当前行成无序列表&a…

npm安装依赖实践总结

node下载地址&#xff1a;https://nodejs.org/en/download/releases 。可以看到node版本、npm版本、node_module版本。 【1】npm的全局安装路径 查看默认值&#xff1a; npm get prefix默认是C:\Users\你的用户名\AppData\Roaming\npm 可以通过 npm config prefix 更改全局…

为什么PCB设计完成后需要放置mark点

PCB设计中的Mark点是指一些标记点&#xff0c;通常用于促进PCB制造和组装过程中的准确性和一致性。这些标记点在制造过程中可以帮助操作员进行自动化定位&#xff0c;从而确保所有部件都被正确组装到其正确位置&#xff0c;这对于确保产品的质量和可靠性至关重要。 下面&#…

springboot抵御即跨站脚本(XSS)攻击

抵御即跨站脚本(XSS)攻击 XSS攻击通常指的是通过利用网站系统保存系统的漏洞&#xff0c;通过巧妙的方法把恶意指令注入到网页&#xff0c;用户加载网页的时候会自动执行恶意脚本 比如&#xff1a; <script>alert(xss); </script> 如果客户能在你的浏览器执行j…

C# Setting.settings . 配置用法

1、定义 在Settings.settings文件中定义配置字段。把作用范围定义为&#xff1a;User则运行时可更改(用户范围的字段数据更改存储在用户信息中&#xff0c;不在该程序文件中)&#xff0c;Applicatiion则运行时不可更改。可以使用数据网格视图(VS软件的Properties 下面的Settin…

几何深度学习 - 利用几何先验知识的深度学习

深度学习很难。 虽然通用逼近定理表明足够复杂的神经网络原则上可以逼近“任何东西”&#xff0c;但不能保证我们可以找到好的模型。 尽管如此&#xff0c;通过明智地选择模型架构&#xff0c;深度学习取得了巨大进步。 这些模型架构对归纳偏差进行编码&#xff0c;为模型提供…

makefile 条件判断语句

文章目录 前言一、条件判断语句的语法说明二、ifeq / ifneq三、ifdef / ifndef代码讲解&#xff1a; 四、经典示例总结 前言 一、条件判断语句的语法说明 makefile 中支持条件判断语句。 可以根据条件的值决定 make 的执行。可以 比较 两个不同变量或者变量和常量值。 条件判…

物理环境与网络通信安全

物理环境与网络通信安全 物理和环境安全环境安全设施安全-安全区域与边界防护传输安全 OSI七层模型ISO/OSI七层模型结构OSI模型特点OSI安全体系结构 TCP/IP协议安全TCP/IP协议结构网络接口层网络互联层核心协议-IP协议传输层协议-TCP&#xff08;传输控制协议&#xff09;传输层…

AMB300系列母线槽红外测温解决方案南沙XX养殖项目案例分享

安科瑞 耿敏花 一、 行业背景 随着当今社会的发展和用电量的急剧上升&#xff0c;现代化工程设施和装备的涌现&#xff0c;封闭式母线即母线槽因方便、节能、载流量大、机械强度高 、安装灵活、寿命长等特点&#xff0c;逐渐取代传统电缆&#xff0c;广泛应用于室内变压…

Window下载Android源码

Android 10源码下载 想要研究Android 源码的同学可以用此方法进行下载。源码从清华大学开源软件镜像站&#xff08;https://mirrors.tuna.tsinghua.edu.cn/help/AOSP/&#xff09;下载。 使用Linux的同学直接参照清华镜像站提供的使用帮助(https://mirrors.tuna.tsinghua.edu…

面试题:react、 vue中的key有什么作用? (key的内部原理)

面试题:react、 vue中的key有什么作用? &#xff08;key的内部原理) 1.虚拟DOM中key的作用: key是虚拟DOM对象的标识&#xff0c;当状态中的数据发生变化时&#xff0c;Vue会根据【新数据】生成【新的虚拟DON】,随后Vue进行【新虚拟DOM】与【旧虚拟DOM】的差异比较&#xff0…

如何用ChatGPT做内容营销方案和选题计划,同时生产和优化内容?

该场景对应的关键词库&#xff08;31个&#xff09;&#xff1a; 内容营销、目标、主题、类型、选题计划、素材、推广策略、优化方案、渠道、目标受众、竞争对手、行业背景、转化率、品牌知名度、客户参与度、销售、发布频率、选题阶段、生产阶段、推广阶段、预算分配、人群特征…

Python+Yolov5舰船侦测识别

程序示例精选 PythonYolov5舰船侦测识别 如需安装运行环境或远程调试&#xff0c;见文章底部个人QQ名片&#xff0c;由专业技术人员远程协助&#xff01; 前言 这篇博客针对<<PythonYolov5舰船侦测识别>>编写代码&#xff0c;代码整洁&#xff0c;规则&#xff0c…

电子招投标采购系统源码-适合于招标代理、政府采购、企业采购、工程交易等业务的企业

招投标管理系统-适合于招标代理、政府采购、企业采购、工程交易等业务的企业 招投标管理系统是一个用于内部业务项目管理的应用平台。以项目为主线&#xff0c;从项目立项&#xff0c;资格预审&#xff0c;标书编制审核&#xff0c;招标公告&#xff0c;项目开标&#xff0c;项…

效率提升一倍,MES管理系统打造车间数字化“筋骨”

在企业生产车间管理中&#xff0c; MES系统可以实时了解现场的生产状态、任务完成情况、物料需求、质量情况等&#xff0c;从而提高企业的生产效率&#xff0c;帮助企业快速响应市场变化&#xff0c;提高产品质量&#xff0c;降低成本。 MES系统是车间制造执行系统的简称…

软考A计划-重点考点-专题十(算法分析与设计)

点击跳转专栏>Unity3D特效百例点击跳转专栏>案例项目实战源码点击跳转专栏>游戏脚本-辅助自动化点击跳转专栏>Android控件全解手册点击跳转专栏>Scratch编程案例 &#x1f449;关于作者 专注于Android/Unity和各种游戏开发技巧&#xff0c;以及各种资源分享&am…

Golang每日一练(leetDay0062) BST迭代器、地下城游戏

目录 173. 二叉搜索树迭代器 Binary Search Tree Iterator &#x1f31f;&#x1f31f; 174. 地下城游戏 Dungeon Game &#x1f31f;&#x1f31f;&#x1f31f; &#x1f31f; 每日一练刷题专栏 &#x1f31f; Golang每日一练 专栏 Python每日一练 专栏 C/C每日一练 …

全景丨0基础学习VR全景制作,平台篇第21章:热点功能-电话

大家好&#xff0c;欢迎观看蛙色VR官方——后台使用系列课程&#xff01; 功能说明 应用场景 热点&#xff0c;指在全景作品中添加各种类型图标的按钮&#xff0c;引导用户通过按钮产生更多的交互&#xff0c;增加用户的多元化体验。 电话热点&#xff0c;即手机端点击热点后可…

sentinel参数配置详细说明

使用的是sentinel-dashboard来配置 流控规则 阈值类型 QPS 当每秒并发数大于配置&#xff0c;则进行限流并发数线程数 当执行的线程数大于配置&#xff0c;则进行限流 单机阈值 配置的具体值 流控模式 直接 默认项&#xff0c;就是在资源名配置的路径进行生效 关联&#…

量子启发生成AI!Zapata Computing联合宝马、MIT优化车辆生产

​ &#xff08;图片来源&#xff1a;网络&#xff09; Zapata Computing是一家量子软件开发公司&#xff0c;致力于为企业构建量子就绪应用解决方案&#xff0c;以解决最复杂的计算问题。5月4日&#xff0c;Zapata Computing宣布发表一篇论文&#xff0c;详细介绍了他们联合宝…