C++11原子操作atomic

news2024/11/23 3:58:49

文章目录

    • 原子操作atomic
      • 原子操作的相关函数
      • 原子操作的特点
        • “平凡的”与“合格的”

原子操作atomic

前面我们介绍了互斥锁等一系列多线程相关操作,这里我们来说下原子操作atomic。
可以理解为原子变量就是将上面的操作进行了整合的一个全新变量,但是实际上它的原理和互斥锁不一样,这关系到操作系统的底层,我也不了解。

原子操作的相关函数

方法作用
is_lock_free检查原子对象是否免锁
load原子地获得原子对象的值
exchange原子地替换原子对象的值并获得它先前持有的值
compare_exchange_weak/compare_exchange_strong原子地比较原子对象与非原子实参的值,相等时进行原子交换,不相等时进行原子加载

除此之外,它还有写特化成员函数,我看了下好像不是很常用,就用到的时候再补充吧。这些函数中,用得多的可能就是load()和compare_exchange_weak(strong)()了。

原子操作的特点

这里就说说原子操作的特点吧:

  • 原子性:原子操作是不可分割的操作,要么完成整个操作,要么不进行操作。在多线程环境中,原子操作保证了共享数据的完整性
  • 线程安全:原子操作提供了线程安全的操作,多个线程可以同时执行原子操作而不会导致数据竞争或不一致的结果
  • 内存顺序:原子操作可以指定内存顺序,即操作的内存访问顺序。C++标准库提供了不同的内存顺序选项,可以控制原子操作的可见性和排序
  • 轻量级:原子操作是一种轻量级的同步机制,相比于锁或互斥量等其他同步机制,原子操作的开销更小
  • 支持不同的数据类型:C++原子操作可以用于不同的数据类型,包括整型、指针和标量类型等

原子性线程安全这两点是有关联的,原子性就保证了原子操作一定是线程安全的;但是内存顺序这点我不是很理解,应该需要计算机组成原理或者OS的相关知识。

在这里,我想要强调的是第三点:支持不同的数据类型
在学完条件变量之后,我写了一段简单的消息队列:

#include <iostream>
#include <thread>
#include <memory>
#include <string>
#include <condition_variable>
#include <list>
#include <atomic>

std::mutex mtx;
std::condition_variable cv;
std::list<std::string> msg;

// 读取数据
void read_thread(){
	while(true){
		std::unique_lock<std::mutex> lock(mtx);

		// 阻塞等待消息(并且解锁)
		// 有消息再执行,没消息不执行
		cv.wait(lock,[&](){ return !msg.empty(); });
		// 获取到互斥锁

		std::cout << "收到消息,解析中:" << std::endl;

		// 将数据从队列中取出
		std::cout << msg.front() << std::endl;
		msg.pop_front();
	}
}

// 写入数据
void write_thread(){
	std::cout << "请输入需要发送的数据:" << std::endl;
	std::string input;
	while(true){
		if(std::cin >> input){
			std::unique_lock<std::mutex> lock(mtx);
			// 将数据放入队列
			msg.push_back(input);
			std::cout << "数据成功输入" << std::endl;

			// 通知read线程,有消息可以接收
			cv.notify_all();
		}
	}
}

int main(){
	std::thread write_(write_thread);
	// 后台运行
	write_.detach();
	
	std::thread read_(read_thread);
	// 后台运行
	read_.detach();

	// 阻塞主线程
	while(true);

	return 0;
}

其中的重点就是条件变量互斥锁,当我学到原子操作的时候我就想:==我能不能将消息队列直接设定为原子操作呢?==于是就有了如下代码:

#include <atomic>
#include <list>
#include <thread>
#include <iostream>
#include <string>
#include <condition_variable>

std::atomic<std::list<std::string>> msg;
std::condition_variable cv;
std::mutex mtx;


void write_thread(){
	std::string input;
	while(true){
		if(std::cin >> input){
			std::cout << "请输入消息:" << std::endl;
			msg.load().emplace_back(input);
			cv.notify_one();
		}
	}
}

void read_thread(){
	while(true){
		std::unique_lock<std::mutex> lock(mtx);
		cv.wait(lock, [&](){ return !msg.load().empty(); });
		std::cout << "收到消息,正在解析:" << std::endl;
		std::cout << msg.load().front() << std::endl;
		msg.load().pop_front();
	}
}

int main(){
	std::thread write_(write_thread);
	write_.detach();

	std::thread read_(read_thread);
	read_.detach();

	while(true);
	return 0;
}

程序在写的时候没有报错提示,但是它跑不起来,有一个全新的报错信息:
在这里插入图片描述

至少我没看懂,同时终端给出了一个函数报错信息:
在这里插入图片描述

于是我就去查询C++参考手册,其中提到:
在这里插入图片描述

其他都差不多能看懂,主要问题就是在这个可平凡复制上,这个我也从来没有听说过,但是在其中出现了之前的报错函数。
于是我就顺着往下查,找到了关于可平凡复制类的说明:
在这里插入图片描述

根据这个说明,我才知道这个报错是因为std::string和std::list都不是可平凡复制类,所以出错了。

“平凡的”与“合格的”

在上面提供的信息中,我们其实还是不能够完全理解它是为什么,因为我们还不知道什么是平凡的
![[…/图片资源/C++/平凡的与合格的.png]]
从这里对“平凡的”的定义,我理解为:”平凡的“就是编译器默认提供的!,例如:C语言中的struct,我们是不能够去编写它的构造函数和析构函数的,相关的操作只有才C++中才支持。因此由编译器提供构造函数和析构函数struct类一定是“平凡的”。相对应的,C++中,由编译器提供构造函数和析构函数class类一般来说也是“平凡的“
并且,在C++中,提供了相应的函数用来评定一个类是否能够使用原子操作,也就是主模板中提到的五个函数:

  • std::is_trivially_copyable<T>::value
  • std::is_copy_constructible<T>::value
  • std::is_move_constructible<T>::value
  • std::is_copy_assignable<T>::value
  • std::is_move_assignable<T>::value

若是这五个函数的返回值有一个为false,就不能够使用原子操作。
对于原子操作,真的没有什么太多的内容,它就跟普通的变量差不了太多,只是它是原子的,具有线程安全的特性

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

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

相关文章

sensitive word 敏感词(脏词) 如何忽略无意义的字符?达到更好的过滤效果?

忽略字符 说明 我们的敏感词一般都是比较连续的&#xff0c;比如 傻帽 那就有大聪明发现&#xff0c;可以在中间加一些字符&#xff0c;比如【傻!#$帽】跳过检测&#xff0c;但是骂人等攻击力不减。 那么&#xff0c;如何应对这些类似的场景呢&#xff1f; 我们可以指定特…

带大家做一个,易上手的家常可乐鸡翅

将鸡翅从冰箱中拿出 泡水解冻 这里 我用的二十个 将葱切段 切一些蒜片 有姜也可以切一些小片下来 这里 家里没姜了 六根干辣椒 一把花椒 等鸡翅化开之后 清洗干净 然后 如下图 中间位置切两刀 方便入味 起锅烧油 然后 下鸡翅 干辣椒 花椒 先翻炒一下 这里不需要放水 鸡翅会…

JavaScript基础知识整理(最全知识点, 精简版,0基础版)

文章目录 一、输入和输出内容 1.1 输出 1.1.1 在浏览器的控制台输出打印 1.1.2 直接在浏览器的页面上输出内容 1.1.3 页面弹出警告对话框 1.2 输入 二、变量 2.1 变量是什么 2.2 变量的声明和赋值 2.3 变量的命名规范和规范 三、变量扩展&#xff08;数组&#xff09; 3.1 数组…

Databend 开源周报第 122 期

Databend 是一款现代云数仓。专为弹性和高效设计&#xff0c;为您的大规模分析需求保驾护航。自由且开源。即刻体验云服务&#xff1a;https://app.databend.cn 。 Whats On In Databend 探索 Databend 本周新进展&#xff0c;遇到更贴近你心意的 Databend 。 支持链式函数调…

windows11 windows 11 (win11 win 11) 怎么安装 Python3 ? numpy? sounddevice? 声音信号处理库?

首先确认要安装的 sounddevice 库&#xff0c;链接&#xff1a;https://python-sounddevice.readthedocs.io/en/0.4.6/ 根据文档&#xff0c;可知最新的 sounddevice 版本是 0.4.6 进入安装页面查看&#xff0c;发现 Newest sounddevice 可以使用 pip 安装&#xff0c;如下图…

mysql中NULL值

mysql中NULL值表示“没有值”&#xff0c;它跟空字符串""是不同的 例如&#xff0c;执行下面两个插入记录的语句&#xff1a; insert into test_table (description) values (null); insert into test_table (description) values ();执行以后&#xff0c;查看表的…

Linux系统编程:高级IO总结

非阻塞IO基本概念 高级IO核心就一个概念&#xff1a;非阻塞IO。 与该概念相对的&#xff0c;就是我们之前学习过的阻塞IO。 非阻塞IO&#xff08;Non-blocking I/O&#xff09;是一种IO模型&#xff0c;用于实现异步IO操作&#xff0c;使应用程序能够在等待IO操作完成的同时…

【Python】 生成二维码

创建了一个使用 python 创建二维码的程序。 下面是生成的程序的图像。 功能描述 输入网址&#xff08;URL&#xff09;。 输入二维码的名称。 当单击 QR 码生成按钮时&#xff0c;将使用 QRname 中输入的字符将 QR 码生成为图像。 程序代码 import qrcode import tkinterd…

【C++】简单工厂模式

2023年12月6日&#xff0c;周三下午 今天又学习了一次简单工厂模式 每多学习一次&#xff0c;都会加深对设计模式的理解 目录 什么是简单工厂模式简单工厂模式的优缺点举例说明 什么是简单工厂模式 简单工厂模式&#xff08;Simple Factory Pattern&#xff09;是一种创建型…

【深度学习】一维数组的 K-Means 聚类算法理解

刚看了这个算法&#xff0c;理解如下&#xff0c;放在这里&#xff0c;备忘&#xff0c;如有错误的地方&#xff0c;请指出&#xff0c;谢谢 需要做聚类的数组我们称之为【源数组】 需要一个分组个数K变量来标记需要分多少个组&#xff0c;这个数组我们称之为【聚类中心数组】…

网络基础---网络层详解(图文清晰易懂!!!)

目录 一、网络层的功能 二、IP数据包的格式 三、ICMP协议 1.ICMP协议的概念和作用 2.ping命令 2.1 ping 的格式 2.2 ping选项 2.3 当我们ping不通时&#xff0c;及服务器出现问题&#xff0c;如何排错 2.4 信息传递时出现的问题类型和具体情况 四、冲突域和广播域 1.…

STM32--GPIO点亮LED灯(手把手,超详细)

写在前面&#xff1a;在前面的学习中&#xff0c;我们学习了STM32的编译环境&#xff08;MDK&#xff09;、时钟树以及GPIO的8种工作模式&#xff1b;这节我们学习正式入门STM32---点亮第一个LED灯&#xff1b;即利用GPIO进行电灯&#xff0c;尽管是一个十分简单的实现&#xf…

2020年第九届数学建模国际赛小美赛A题自由泳解题全过程文档及程序

2020年第九届数学建模国际赛小美赛 A题 自由泳 原题再现&#xff1a; 在所有常见的游泳泳姿中&#xff0c;哪一种最快&#xff1f;哪个冲程推力最大&#xff1f;在自由泳项目中&#xff0c;游泳者可以选择他们的泳姿&#xff0c;他们通常选择前面的爬行。然而&#xff0c;游泳…

知识付费商城7.0.3开心学习版,新增供货商功能

彩虹知识付费商城7.0.3小森升级版新增供货商开心学习版。仅供开发参考&#xff0c;切勿正式商用。 1.新增邮件提醒功能&#xff0c;支持给用户发订单、结算等邮件通知 2.支持给管理员发送提现、域名审核等邮件通知 3.支持设置手续费最低扣除金额 4.修复了其他一些已知问题 …

激光雷达标定板提高扫地机器人感知环境能力和清洁效率

智能扫地机器人的激光雷达标定板是一种用于校准激光雷达的设备&#xff0c;它通常由不同反射率的涂料涂覆在板面上&#xff0c;用于接收激光雷达发出的激光束并将其反射回来&#xff0c;从而帮助校准激光雷达的测量参数。在自动驾驶和机器人领域&#xff0c;激光雷达和相机的联…

HDFS Java API 基本操作实验

文章目录 一、实验环境二、实验内容&#xff08;一&#xff09;数据准备&#xff08;二&#xff09;编程环境准备&#xff08;三&#xff09;使用Hadoop API操作HDFS文件系统&#xff08;四&#xff09;使用Hadoop API Java IO流操作HDFS文件系统 三、实验步骤&#xff08;一&…

OpenCL学习笔记(二)手动编译开发库(win10+vs2019)

前言 有时需求比较特别&#xff0c;可能需要重新编译opencl的sdk库。本文档简单记录下win10下&#xff0c;使用vs2019编译的过程&#xff0c;有需要的小伙伴可以参考下 一、获取源码 项目地址&#xff1a;GitHub - KhronosGroup/OpenCL-SDK: OpenCL SDK 可以直接使用git命令…

【剑指offer|图解|数组】寻找文件副本 + 螺旋遍历二维数组

&#x1f308;个人主页&#xff1a;聆风吟 &#x1f525;系列专栏&#xff1a;数据结构、剑指offer每日一练 &#x1f516;少年有梦不应止于心动&#xff0c;更要付诸行动。 文章目录 一. ⛳️寻找文件副本(题目难度&#xff1a;简单)1.1 题目1.2 示例1.3 限制1.4 解题思路一c代…

2023年第一次系统架构师备考经历

12月7日成绩已经出来&#xff0c;果然最担心的案例分析没有过&#xff0c;才考了40分&#xff0c;还差5分&#xff0c;我就可以一次拿下证书&#xff0c;好可惜啊&#xff0c;今年的题出的有点偏&#xff0c;大数据居然成为必答题&#xff0c;平常是搞Java&#xff0c;大数据方…

做抖店代发,新手如何定类目?五大类目优缺点分析!

我是电商珠珠 类目是店铺的方向&#xff0c;只有将店铺的定位确定好&#xff0c;才能超越大部分的同行。 我经常跟我的学生讲&#xff0c;选择类目的时候不能瞎选&#xff0c;要学会去分析市场&#xff0c;由于大部分的学员前期都是新手小白&#xff0c;所以我们这边会负责给…