C++11并发与多线程笔记(10) future其他成员函数、shared_future、atomic

C++11并发与多线程笔记(10) future其他成员函数、shared_future、atomic

  • 1、std::future 的成员函数
    • 1.1 std::future_status
  • 2、std::shared_future:也是个类模板
  • 3、std::atomic原子操作
    • 3.1 原子操作概念引出范例:
    • 3.2 基本的std::atomic用法范例

1、std::future 的成员函数

1.1 std::future_status

status = result.wait_for(std::chrono::seconds(几秒));

卡住当前流程,等待std::async()的异步任务运行一段时间,然后返回其状态std::future_status。如果std::async()的参数是std::launch::deferred(延迟执行),则不会卡住主流程。
std::future_status是枚举类型,表示异步任务的执行状态。类型的取值有

  • std::future_status::timeout
  • std::future_status::ready
  • std::future_status::deferred
#include <iostream>
#include <future>
using namespace std;int mythread() {cout << "mythread() start" << "threadid = " << std::this_thread::get_id() << endl;std::chrono::milliseconds dura(5000);std::this_thread::sleep_for(dura);cout << "mythread() end" << "threadid = " << std::this_thread::get_id() << endl;return 5;
}int main() {cout << "main" << "threadid = " << std::this_thread::get_id() << endl;std::future<int> result = std::async(mythread);cout << "continue........" << endl;//cout << result1.get() << endl; //卡在这里等待mythread()执行完毕,拿到结果//等待6秒std::future_status status = result.wait_for(std::chrono::seconds(6));if (status == std::future_status::timeout) {//超时:表示线程还没有执行完cout << "超时了,线程还没有执行完" << endl;}else if(status==std::future_status::ready){cout<<"线程成功执行完毕,返回"<<endl;cout<<result.get()<,endl;}else if(status==std::future_status::deferred){//如果async的第一个参数被设置为std::launch::deferred,则本条件成立cout<<"线程被延迟!!"<<endl;//mythread在主线程执行cout<<result.get()<,endl;}cout<<"I love China!"<<endl;return 0;
}

在这里插入图片描述

注意get()只能使用一次。get()函数的设计是一个移动语义,相当于将result中的值移动了,再次get就报告了异常。

2、std::shared_future:也是个类模板

  • std::future的 get() 成员函数是转移数据
  • std::shared_future 的 get()成员函数是复制数据
#include <thread>
#include <iostream>
#include <future>
using namespace std;int mythread() {cout << "mythread() start" << "threadid = " << std::this_thread::get_id() << endl;std::chrono::milliseconds dura(5000);std::this_thread::sleep_for(dura);cout << "mythread() end" << "threadid = " << std::this_thread::get_id() << endl;return 5;
}void mythread2(std::shared_future<int> &tmpf){//此时使用shared_futurecout<<"mythread2() start"<<"threadid="<<std::this_thread::get_id()<<endl;auto result=tmpf.get();//可以get多次cout<<"mythread2 result="<<result<,endl;
}
int main() {cout << "main" << "threadid = " << std::this_thread::get_id() << endl;std::packaged_task<int()> mypt(mythread);std::thread t1(std::ref(mypt));std::future<int> result = mypt.get_future();bool ifcanget = result.valid(); //判断future中的值是不是一个有效值//方法1std::shared_future<int> result_s(result.share()); //执行完毕后result_s里有值,而result里空了//方法2//std::shared_future<int> result_s(std::move(result));//方法3//通过get_future返回值直接构造一个shared_future对象//std::shared_future<int> result_s(mypt.get_future());t1.join();auto myresult1 = result_s.get();auto myresult2 = result_s.get();std:: thread t2(mythread2,std::ref(result_s));t2.join();//等待线程执行完毕cout << "good luck" << endl;return 0;
}

3、std::atomic原子操作

3.1 原子操作概念引出范例:

互斥量:多线程编程中用于保护共享数据:先锁住-> 操作共享数据->解锁。

两个线程,对一个变量进行操作,一个线程这个变量的值,一个线程往这个变量中值。

(1) 即使是一个简单变量的读取和写入操作,如果不加锁,也有可能会导致读写值混乱(一条C++语句会被拆成3、4条汇编语句来执行,所以仍然有可能混乱)

#include <iostream>
#include <thread>
using namespace std;
int g_count = 0;void mythread1() {for (int i = 0; i < 1000000; i++) {g_count++;}return;
}int main() {std::thread t1(mythread1);std::thread t2(mythread1);t1.join();t2.join();cout << "正常情况下结果应该是200 0000次,实际是" << g_count << endl;
}

在这里插入图片描述
原因:一条C++语句会被拆成3、4条汇编语句,线程上下文切换就有可能打乱。

(2)如果使用互斥量 mutex解决这个问题

#include <iostream>
#include <thread>
#include <mutex>
using namespace std;
int g_count = 0;
std::mutex mymutex;void mythread1() {for (int i = 0; i < 1000000; i++) {std::unique_lock<std::mutex> u1(mymutex);g_count++;}
}int main() {std::thread t1(mythread1);std::thread t2(mythread1);t1.join();t2.join();cout << "正常情况下结果应该是200 0000次,实际是" << g_count << endl;
}

在这里插入图片描述

3.2 基本的std::atomic用法范例

可以把原子操作理解成一种:不需要用到互斥量加锁(无锁)技术的多线程并发编程方式。

原子操作:在多线程中不会被打断的程序执行片段
从效率上来说,原子操作要比互斥量的方式效率要

互斥量的加锁一般是针对一个代码段,而原子操作针对的一般都是一个变量

原子操作,一般都是指“不可分割的操作”;也就是说这种操作状态要么是完成的,要么是没完成的,不可能出现半完成状态。

std::atomic来代表原子操作,是个类模板。其实std::atomic是用来封装某个类型的值的

案例1:

#include <iostream>
#include <thread>
#include <atomic> //添加#include <atomic>头文件
using namespace std;
std::atomic<int> g_count = 0; //封装了一个类型为int的 对象(值)void mythread1() {for (int i = 0; i < 1000000; i++) {g_count++;//对应的的操作是原子操作(不会被打断)}
}int main() {std::thread t1(mythread1);std::thread t2(mythread1);t1.join();t2.join();cout << "正常情况下结果应该是200 0000次,实际是" << g_count << endl;
}

在这里插入图片描述
案例2(bool 案例):

#include <iostream>
#include <thread>
#include <atomic>
using namespace std;
std::atomic<bool> g_ifEnd = false; //封装了一个类型为bool的 对象(值)void mythread() {std::chrono::milliseconds dura(1000);//1swhile (g_ifEnd == false) {//系统没要求线程退出,所以本线程可以干自己想干的事情cout << "thread id = " << std::this_thread::get_id() << "运行中" << endl;std::this_thread::sleep_for(dura);}cout << "thread id = " << std::this_thread::get_id() << "运行结束" << endl;
}int main() {std::thread t1(mythread);std::thread t2(mythread);std::chrono::milliseconds dura(5000);//5sstd::this_thread::sleep_for(dura);g_ifEnd = true;//对原子对象的写操性,让线程自行运行结束;t1.join();t2.join();cout << "程序执行完毕" << endl;
}

在这里插入图片描述
总结:

  1. 原子操作一般用于计数或者统计(如累计发送多少个数据包,累计接收到了多少个数据包),多个线程一起统计,这种情况如果不使用原子操作会导致统计发生混乱。

  2. 写商业代码时,如果不确定结果的影响,最好自己先写一小段代码调试。或者不要使用。

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

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

相关文章

Springboot+mybaits-plus+h2集成产生的一些问题(not found tables)

一、问题描述 org.h2.jdbc.JdbcSQLSyntaxErrorException: Table "EP_MAPPING" not found (this database is empty);大概就是说在引入mybatis-plus的依赖后&#xff0c;找不到数据库找不到表的问题。 排查方向&#xff1a;在引入mybatish2时&#xff0c;是可以正常…

【vue3+ts项目】配置eslint校验代码工具,eslint+prettier+stylelint

1、运行好后自动打开浏览器 package.json中 vite后面加上 --open 2、安装eslint npm i eslint -D3、运行 eslint --init 之后&#xff0c;回答一些问题&#xff0c; 自动创建 .eslintrc 配置文件。 npx eslint --init回答问题如下&#xff1a; 使用eslint仅检查语法&…

解决出海痛点:亚马逊云科技助力智能涂鸦,实现设备互联互通

今年6月&#xff0c;《财富》&#xff08;中文版&#xff09;发布“2023年值得关注的中国出海主力”盘点&#xff0c;在七个赛道中聚焦不断开拓新领域、影响力与日俱增的出海企业。涂鸦智能顺利入选&#xff0c;作为一家全球化公司&#xff0c;相比于产品直接到海外销售的传统出…

wazuh初次理解-8-23

一、wazuh配置&#xff1a; 1、进入官网下载OVA启动软件&#xff1a; Virtual Machine (OVA) - Installation alternatives 2、进入虚拟机进行配置&#xff1a; 3、登录提示&#xff1a; 4、将网络连接模式更改为NAT&#xff0c;否则不能上网&#xff1b; 4、重启网络&#…

ahooks.js:一款强大的React Hooks库及其API使用教程(四)

一、ahooks.js简介二、ahooks.js安装三、继续ahooks.js API的介绍与使用教程51. useResetState52. useUpdateLayoutEffect53. useDeepCompareLayoutEffect54. useRafInterval55. useRafTimeout56. useTimeout57. useLockFn58. useDocumentVisibility59. useDrop60. useDrag 一、…

AI大模型潮水中,医疗数字化加速「求解」

蝴蝶挥动翅膀&#xff0c;医疗行业每个角落开始连锁反应&#xff0c;曾经被忽视的问题也愈发明显。但与之对应的是&#xff0c;对数字化和AI大模型的价值认可&#xff0c;在中国医疗赛道也正在加速来临。 作者|斗斗 编辑|皮爷 出品|产业家 重庆市某地方人民医院&#xf…

如何实现element UI中table操作栏更多按钮的展示与折叠?

解决思路: ​ 直接使用elementUI文档上Popover 弹出框组件 废话不多说,直接上代码吧 <el-table :data="locationList" v-loading="loading" border class="table" ref="multipleTable" @selection-change="handleSelecti…

【C++】做一个飞机空战小游戏(十二)——游戏源代码、音效、图标等资源文件

[导读]本系列博文内容链接如下&#xff1a; 【C】做一个飞机空战小游戏(一)——使用getch()函数获得键盘码值 【C】做一个飞机空战小游戏(二)——利用getch()函数实现键盘控制单个字符移动【C】做一个飞机空战小游戏(三)——getch()函数控制任意造型飞机图标移动 【C】做一个飞…

微信小程序创建项目以及注意事项

1.申请账号并完善信息 2.下载安装开发工具 3.开发小程序 4.上传代码 5.提交审核 6.发布 创建项目 根据需求选择模板&#xff0c;也可以不选择模板 创建完毕之后 进入页面点击终端 然后新建终端 输入npm init 一直按回车即可 安装成功 出现package.json 如何使用组件&#x…

Android 12系统源码_输入事件(一)HOME按键事件响应流程

前言 本文我们现在主要分析一下android系统对HOME按键的响应过程&#xff0c;HOME按键事件是属于系统级别的按键事件监听&#xff0c;而在Android系统中&#xff0c;系统级别的按键处理逻辑都在PhoneWindowManager这个类中。 一、interceptKeyBeforeDispatching方法分发按键事…

IC芯片 trustzone学习

搭建Airplay TA环境需要在IC的TrustZone中进行。TrustZone是一种安全技术&#xff0c;用于隔离安全和非安全环境&#xff0c;并保护敏感文件。在TrustZone中&#xff0c;我们需要编写一个叫做TA&#xff08;Trusted Application&#xff09;的应用程序来控制这些私密文档。 &am…

SpringBoot一些困惑及梳理

Spring中常用的classpath前缀到底指向哪里? classpath实际就是和java命令行运行时指定的classpath是同一个概念&#xff0c;在ideamaven中也就是指向target/classes目录。不要被网上哪些复制粘贴的文章所迷惑。classpath: 和 classpath*: 到底什么区别? classpath: 实际就是当…

Python土力学与基础工程计算.PDF-土的三项组成

5.3 Python求解 Python 求解代码如下&#xff1a; 1. # 定义已知参数 2. G_s 2.7 # 比重 3. w 0.2 # 含水量 4. e 0.6 # 孔隙比 5. gamma_w 9.81 # 水的重度 6. 7. # 根据公式计算饱和度 8. S_r G_s * w / e 9. print("饱和度为", S_r) 10. 11.…

js将搜索的关键字加颜色

js将搜索的关键字加颜色 使用正则匹配关键字并加入span标签&#xff0c;页面渲染时使用v-html渲染即可 // 文本框内容 let searchCont 测试;const reg new RegExp((${searchCont.value}), g); let data 图片保存测试A; data data.replace(reg, <span style"color:…

vscode+ros开发环境搭建

目录 介绍 前提 vscode安装 vscode插件安装 工作空间准备 打开vscode 创建catkin包 编写cpp代码 编译 运行 启动ros服务 监听话题 启动ros测试 介绍 ros开发是机器人开发中必不可少的工作&#xff0c;语言选择可以是c,也可以是python。工具的话&#xff0c;不能像wi…

基于YOLOv8模型的五类动物目标检测系统(PyTorch+Pyside6+YOLOv8模型)

摘要&#xff1a;基于YOLOv8模型的五类动物目标检测系统可用于日常生活中检测与定位动物目标&#xff08;狼、鹿、猪、兔和浣熊&#xff09;&#xff0c;利用深度学习算法可实现图片、视频、摄像头等方式的目标检测&#xff0c;另外本系统还支持图片、视频等格式的结果可视化与…

Github 博客搭建

Github 博客搭建 准备工作 准备一个 github 账号建立 github 仓库&#xff0c;仓库名为 username.github.io设置仓库为 publicclone 仓库&#xff0c;写入一个 index.html 文件&#xff0c;推送到仓库&#xff08;许多网上的教程会有 choose theme&#xff0c;但是新版本的 g…

「Java」《Java集合框架详解:掌握常用集合类,提升开发效率》

Java集合框架详解&#xff1a;掌握常用集合类&#xff0c;提升开发效率 摘要&#xff1a;一、 引言1.1 Java 集合框架的作用和重要性&#xff0c;在开发中的应用场景 二. 集合框架概述2.1 集合框架的基本目标和设计思想2.2 层次结构图示&#xff0c;各个集合接口之间的关系 三.…

AI 绘画Stable Diffusion 研究(十四)SD 图生图+剪映制作人物说话视频

大家好&#xff0c;我是风雨无阻。 前一篇&#xff0c;我们详细介绍了使用 SadTlaker制作数字人视频案例&#xff0c;感兴趣的朋友请前往查看:AI 绘画Stable Diffusion 研究&#xff08;十三&#xff09;SD数字人制作工具SadTlaker使用教程。 对于没有安装 SadTlaker 插件的朋友…

CH583/2构建工程教程

CH583/2构建工程教程 绪论资源移植步骤准备移植步骤一步骤二 工程配置修改工程名修改前修改后 工程配置修改资源文件 修改C/C general修改C/C构建修改汇编交叉编译修改C交叉编译修改GNU RISC-V Cross Linker 修改跟编译 移植注意事项 绪论 资源 CH583/2的SDK下载 移植步骤 …