C++并发与多线程(高级函数async)
async
在 C++ 中,async
关键字用于实现异步编程,它允许你定义异步操作,这些操作可以在后台执行,而不会阻塞当前线程。这是 C++11 引入的特性,与 std::async
函数和 std::future
类一起使用。与thread函数模板的区别在于async可以有返回值,thread无返回值。
简单入门
// ConsoleApplication10.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//#include <iostream>
#include <vector>
#include <map>
#include <string>
#include <thread>
#include <mutex>
#include <cstdint>
#include <future>#include <list>
using namespace std;int mythread()
{cout << "func " << " threadid = " << this_thread::get_id() << " start " << endl << endl;std::chrono::milliseconds dura(3000);std::this_thread::sleep_for(dura);cout << "func " << " threadid = " << this_thread::get_id() <<" end " << endl << endl;return 5;}int main()
{cout << "=========================================== " << " threadid = " << this_thread::get_id() << endl << endl;std::future<int> ret = std::async(mythread);cout << ret.get() << endl; //堵塞获取值,注意:get函数只能调用一次,不能多次调用//注意:如果不写get,程序会等子线程退出后在自行退出cout << "=========================================== " << " threadid = " << this_thread::get_id() << endl << endl;return 0;
}
中级过度
// ConsoleApplication10.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//#include <iostream>
#include <vector>
#include <map>
#include <string>
#include <thread>
#include <mutex>
#include <cstdint>
#include <future>#include <list>
using namespace std;class A
{
public:int mythread(int myint){cout << "func " << " threadid = " << this_thread::get_id() << " start " << endl << endl;cout << "myint = " << myint << endl;std::chrono::milliseconds dura(3000);std::this_thread::sleep_for(dura);cout << "func " << " threadid = " << this_thread::get_id() << " end " << endl << endl;return 5;}
};int main()
{cout << "=========================================== " << " threadid = " << this_thread::get_id() << endl << endl;A a;int num = 100;std::future<int> ret = std::async(&A::mythread,&a,num);//传入可调用对象 &a == std::ref(a)都是引用传递 相当于传递了this指针。cout << ret.get() << endl; //堵塞获取值cout << "=========================================== " << " threadid = " << this_thread::get_id() << endl << endl;return 0;
}
高手使用
在 C++ 中,std::async
函数用于启动一个异步任务,并且可以与 std::launch
策略一起使用来控制任务的执行方式。std::launch
是 std::launch
枚举的一个值,它指示 std::async
以延迟(deferred)的方式执行给定的可调用对象。
当你使用 std::launch::deferred
时,std::async
将立即返回一个 std::future
对象,但不会立即执行传入的函数或函数对象。相反,函数的执行被延迟,直到你显式地请求结果,通常是通过调用 std::future::get
方法。这允许你在不阻塞当前线程的情况下启动异步操作。
意思就是说在调用get的函数,才开始执行程序,且是在主线程执行的,不调用的话函数不会运行。
// ConsoleApplication10.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//#include <iostream>
#include <vector>
#include <map>
#include <string>
#include <thread>
#include <mutex>
#include <cstdint>
#include <future>#include <list>
using namespace std;class A
{
public:int mythread(int myint){cout << "func " << " threadid = " << this_thread::get_id() << " start " << endl << endl;cout << "myint = " << myint << endl;std::chrono::milliseconds dura(3000);std::this_thread::sleep_for(dura);cout << "func " << " threadid = " << this_thread::get_id() << " end " << endl << endl;return 5;}
};int main()
{cout << "=========================================== " << " threadid = " << this_thread::get_id() << endl << endl;A a;int num = 100;std::future<int> ret = std::async(std::launch::async|std::launch::deferred,&A::mythread,&a,num);//传入可调用对象 &a == std::ref(a)都是引用传递 相当于传递了this指针。cout << ret.get() << endl; //堵塞获取值cout << "=========================================== " << " threadid = " << this_thread::get_id() << endl << endl;return 0;
}
package_task
在 C++ 中,std::packaged_task
是一个类模板,它用于包装任何可调用对象(如函数、lambda 表达式、函数对象等),以便它可以被异步调用。它的返回值或抛出的异常被存储在一个共享状态中,可以通过 std::future
对象访问。std::packaged_task
与 std::future
结合使用时,可以轻松管理异步操作。
以下是如何使用 std::packaged_task
的基本步骤:
-
创建
std::packaged_task
对象:你可以创建一个std::packaged_task
对象,并将一个可调用对象(如函数或 lambda 表达式)传递给它。 -
获取
std::future
对象:通过调用get_future()
方法,你可以获取一个std::future
对象,该对象可以用来获取异步操作的结果。 -
启动异步任务:你可以通过在新的线程中调用
std::packaged_task
对象来启动异步任务。 -
等待结果:使用
std::future
对象的get()
方法来等待异步操作完成并获取结果。
简单入门
// ConsoleApplication10.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//#include <iostream>
#include <vector>
#include <map>
#include <string>
#include <thread>
#include <mutex>
#include <cstdint>
#include <future>#include <list>
using namespace std;int mythread(int myint)
{cout << "func " << " threadid = " << this_thread::get_id() << " start " << endl << endl;cout << "myint = " << myint << endl;std::chrono::milliseconds dura(3000);std::this_thread::sleep_for(dura);cout << "func " << " threadid = " << this_thread::get_id() << " end " << endl << endl;return 5;}int main()
{cout << "=========================================== " << " threadid = " << this_thread::get_id() << endl << endl;//std::packaged_task类模板std::packaged_task<int(int)>mypt(mythread); //把函数mytherad通过package_task包装std::thread t1(std::ref(mypt),120);t1.join(); //这里的join不可以省略
//执行完毕future<int>ret = mypt.get_future(); //获取到future对象。cout << "fun finish ret = " << ret.get() << endl;cout << "=========================================== " << " threadid = " << this_thread::get_id() << endl << endl;return 0;
}
中级过度
// ConsoleApplication10.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//#include <iostream>
#include <vector>
#include <map>
#include <string>
#include <thread>
#include <mutex>
#include <cstdint>
#include <future>#include <list>
using namespace std;int mythread(int myint)
{cout << "func " << " threadid = " << this_thread::get_id() << " start " << endl << endl;cout << "myint = " << myint << endl;std::chrono::milliseconds dura(3000);std::this_thread::sleep_for(dura);cout << "func " << " threadid = " << this_thread::get_id() << " end " << endl << endl;return 5;}int main()
{cout << "=========================================== " << " threadid = " << this_thread::get_id() << endl << endl;//std::packaged_task类模板std::packaged_task<int(int)>mypt([](int num) { cout << "func " << " threadid = " << this_thread::get_id() << " start " << endl << endl;cout << "myint = " << num << endl;std::chrono::milliseconds dura(3000);std::this_thread::sleep_for(dura);cout << "func " << " threadid = " << this_thread::get_id() << " end " << endl << endl;return 5;}); //把函数mytherad通过package_task包装mypt(300); //包装对象可以直接调用。,在主线程执行,未创建线程//执行完毕future<int>ret = mypt.get_future(); //获取到future对象。cout << "fun finish ret = " << ret.get() << endl;cout << "=========================================== " << " threadid = " << this_thread::get_id() << endl << endl;return 0;
}
高手使用
// ConsoleApplication10.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//#include <iostream>
#include <vector>
#include <map>
#include <string>
#include <thread>
#include <mutex>
#include <cstdint>
#include <future>#include <list>
using namespace std;class A
{
public:int mythread(int myint){cout << "func " << " threadid = " << this_thread::get_id() << " start " << endl << endl;cout << "myint = " << myint << endl;std::chrono::milliseconds dura(3000);std::this_thread::sleep_for(dura);cout << "func " << " threadid = " << this_thread::get_id() << " end " << endl << endl;return 5;}
};int mythread(int myint)
{cout << "func " << " threadid = " << this_thread::get_id() << " start " << endl << endl;cout << "myint = " << myint << endl;std::chrono::milliseconds dura(3000);std::this_thread::sleep_for(dura);cout << "func " << " threadid = " << this_thread::get_id() << " end " << endl << endl;return 5;}vector<std::packaged_task<int(int)> > mystatsks;int main()
{cout << "=========================================== " << " threadid = " << this_thread::get_id() << endl << endl;//std::packaged_task类模板std::packaged_task<int(int)>mypt([](int num) { cout << "func " << " threadid = " << this_thread::get_id() << " start " << endl << endl;cout << "myint = " << num << endl;std::chrono::milliseconds dura(3000);std::this_thread::sleep_for(dura);cout << "func " << " threadid = " << this_thread::get_id() << " end " << endl << endl;return 5;}); //把函数mytherad通过package_task包装cout << "mypt.valid = " << mypt.valid() << endl;//mystatsks.push_back( (mypt) ); //默认是调用拷贝构造,此处内部被删除了mystatsks.push_back(std::move(mypt)); //移动到容器中。 mypt就无效了cout << "mypt.valid = " << mypt.valid() << endl;std::packaged_task<int(int)>mypt2;auto it = mystatsks.begin(); //获取第一个元素mypt2 = std::move(*it); //移动到mypt2cout <<"mystsks.size() = "<< mystatsks.size() << endl;mystatsks.erase(it);mypt2(123);std::future<int>ret =mypt2.get_future() ;cout << "ret = " << ret.get();cout << "=========================================== " << " threadid = " << this_thread::get_id() << endl << endl;return 0;
}
promise
在 C++11 及以后的版本中,std::promise
是一个模板类,它提供了一种方式来存储值或异常,并且可以在稍后某个时刻通过 std::future
对象访问这些值或异常。std::promise
通常与 std::future
一起使用,以实现线程间的数据传递或同步。
以下是 std::promise
的一些关键特点和用法:
-
存储值:
std::promise
可以存储一个值,这个值可以是任何类型,包括自定义类型。 -
存储异常:如果
std::promise
存储了一个异常,那么当std::future
对象尝试获取值时,这个异常会被抛出。 -
设置值:一旦
std::promise
被设置(通过set_value
或set_value_at_thread
方法),它就不能再次被设置。如果尝试再次设置,将抛出std::future_error
异常。 -
获取值:
std::future
对象使用get
方法从关联的std::promise
获取值。如果std::promise
存储了异常,get
将抛出这个异常。 -
等待:
std::future
对象可以使用wait
或wait_for
方法等待std::promise
设置值。 -
移动语义:
std::promise
对象可以被移动,但不能被复制。
其他线程使用可以参数我主页中的 C语言:高级并发操作(线程)文章。
相关文章:
C++并发与多线程(高级函数async)
async 在 C 中,async 关键字用于实现异步编程,它允许你定义异步操作,这些操作可以在后台执行,而不会阻塞当前线程。这是 C11 引入的特性,与 std::async 函数和 std::future 类一起使用。与thread函数模板的区别在于as…...

安卓课设版算法计算器
安卓课设版算法计算器(HNUST) 前言: 如果只想看函数使用说明请跳转到“四、使用函数介绍” 该版本为课设版,富含多个界面,是前版的plus版本,进行了更多的复杂化操作,故因此会觉得对于计算器有点…...

X-Forwarded-For注入漏洞
0x00环境介绍 靶机http://219.153.49.228:48033,通过注入完成找到网站的key。 1|00x01复现过程 1.访问网站使用admin/admin登入,用burpsuite截包寻找注入点 >>截到的包,正常放包回显内容 >>加X-forwarded-for:1.1.1.1回显IP数据改变&…...

Linux - MySQL迁移至一主一从
Linux - MySQL迁移至一主一从 迁移准备安装MySQL ibd文件迁移原服务器操作目标服务器操作 一主一从增量同步异常解决结尾 首先部分单独安装MySQL,请参考Linux - MySQL安装,迁移数据量比较大约400G左右且网络不通故使用文件迁移,需开启一段时间…...

《变形金刚:赛博坦的陨落》游戏启动难题:‘buddha.dll’缺失的七大修复策略
《变形金刚:赛博坦的陨落》游戏启动时提示buddha.dll缺失:原因与解决方案 作为一名软件开发从业者,我在日常工作中经常遇到电脑游戏运行时出现的各种问题,如文件丢失、文件损坏和系统报错等。今天,我们就来探讨一下《…...

51c嵌入式~单片机~合集2
我自己的原文哦~ https://blog.51cto.com/whaosoft/12362395 一、不同的电平信号的MCU怎么通信? 下面这个“电平转换”电路,理解后令人心情愉快。电路设计其实也可以很有趣。 先说一说这个电路的用途:当两个MCU在不同的工作电压下工作&a…...
java Resource 记录
Java 注解 Resource 是一个标准的 Java 注解,用于注入资源。它可以用于注入任何资源,如文件、数据库连接、用户定义的资源等。它可以通过名称或类型进行注入。 当你想要注入一个bean到你的类中时,你可以使用Resource注解。 解决方案1&#…...
Avalonia 开发环境准备
总目录 前言 介绍如何搭建 Avalonia 开发环境。 一、在线开发环境搭建 请先安装您选择的受支持的IDE。Avalonia 支持 Visual Studio、Rider 和 Visual Studio Code。 详见:https://docs.avaloniaui.net/zh-Hans/docs/get-started/install 1. 使用 Visual Studio 20…...
C# 中 Console.WriteLine($“{DateTime.Now.Date}“); win 和 docker容器输出不同
Console.WriteLine($"{DateTime.Now.Date}"); //windowns输出:2024/12/10 0:00:00 //docker容器输出:12/10/2024 00:00:00 这是由于 不同的文化区域(CultureInfo)设置 导致的时间格式差异。在 Windows 系统…...

回型矩阵:JAVA
解题思路: 通过定义四条边界;top,left,right,bottom,来循环,当top>bottom&&left>right的时候循环终止 循环结束的条件: 链接:登录—专业IT笔试面试备考平台_牛客网 来源:牛客网 题目描述…...
从零开始学习 sg200x 多核开发之 sophpi 编译生成 fip.bin 流程梳理
本文主要介绍 sophpi 编译生成 fip.bin 流程。 1、编译前准备 sophpi 的基本编译流程如下: $ source build/cvisetup.sh $ defconfig sg2002_wevb_riscv64_sd $ clean_all $ build_all $ pack_burn_image注: 需要在 bash 下运行clean_all 非必要可以不…...

python--在服务器上面创建conda环境
今天刚开始使用服务器的时候使用上面的公共环境发现老师缺少模块, [guoyupingcins195 ~]$ conda --version Traceback (most recent call last): File "/home/miniconda3/bin/conda", line 12, in <module> from conda.cli import main Fil…...

day15 python(3)——python基础(完结!!)
【没有所谓的运气🍬,只有绝对的努力✊】 目录 1、函数 1.1 函数传参中的拆包 1.2 匿名函数的定义 1.3 匿名函数练习 1.4 匿名函数应用——列表中的字典排序 2、面向对象 OOP 2.1 面向对象介绍 2.2 类和对象 2.3 类的构成和设计 2.4 面向对象代码…...
/:087启动游戏时提示丢失”d3dx···.dll””VCOMP···.dll”
/:087启动游戏时提示丢失”d3dx.dll””VCOMP.dll”或遇到应用程序无法正常启动(0xc000007b)和游戏有图像没有声音等情况。 主要是因为系统缺少大型游戏/软件运行的必备组件,这些组件有DirectX,Visual C2010,2012&…...
利用PHP和phpSpider进行图片爬取及下载
利用PHP和phpSpider进行图片爬取及下载,可以遵循以下步骤。phpSpider是一个开源的PHP爬虫框架,它可以帮助你轻松地抓取网页内容。以下是一个基本的步骤指南: 1. 安装phpSpider 首先,你需要确保你已经安装了Composer(…...
企业架构划分探讨:业务架构与IT架构的利与弊
在企业架构(EA)的江湖里,大家一直致力于如何把企业的复杂性简化成有条有理的架构蓝图。有人选择把企业架构分成业务架构和IT架构,而IT架构又进一步细分为应用架构、数据架构和技术架构。但一提到这种划分方式,总有人跳…...

Java设计模式 —— 【结构型模式】桥接模式详解
前言 现在有一个需求,需要创建不同的图形,并且每个图形都有可能会有不同的颜色。 首先我们看看用继承来实现: 我们可以发现有很多的类,假如我们再增加一个形状或再增加一种颜色,就需要创建更多的类。 试想…...

MySQL学习之DDL操作
目录 数据库的操作 创建 查看 选择 删除 修改 数据类型 表的创建 表的修改 表的约束 主键 PRIMARY KEY 唯一性约束 UNIQUE 非空约束 NOT NULL 外键约束 约束小结 索引 索引分类 常规索引 主键索引 唯一索引 外键索引 优点 缺点 视图 创建 删除 修改…...

游戏AI实现-寻路算法(A*)
A*(A-star)是一种图遍历和寻路算法,由于其完整性、最优性和最佳效率,它被用于计算机科学的许多领域。给定一个加权图、一个源节点和一个目标节点,该算法将找到从源到目标的最短路径(相对于给定的权重&#…...

spring学习(spring的IoC思想、spring容器、spring配置文件、依赖注入(DI)、BeanProxy机制(AOP))
目录 一、spring-IoC。 (1)spring框架。(诞生原因及核心思想) 1、为什么叫框架? 2、spring框架诞生的技术背景。 (2)控制反转(IoC)。 (3)spring的Bean工厂和IoC容器。 &a…...

大数据学习栈记——Neo4j的安装与使用
本文介绍图数据库Neofj的安装与使用,操作系统:Ubuntu24.04,Neofj版本:2025.04.0。 Apt安装 Neofj可以进行官网安装:Neo4j Deployment Center - Graph Database & Analytics 我这里安装是添加软件源的方法 最新版…...

CTF show Web 红包题第六弹
提示 1.不是SQL注入 2.需要找关键源码 思路 进入页面发现是一个登录框,很难让人不联想到SQL注入,但提示都说了不是SQL注入,所以就不往这方面想了 先查看一下网页源码,发现一段JavaScript代码,有一个关键类ctfs…...

visual studio 2022更改主题为深色
visual studio 2022更改主题为深色 点击visual studio 上方的 工具-> 选项 在选项窗口中,选择 环境 -> 常规 ,将其中的颜色主题改成深色 点击确定,更改完成...
3403. 从盒子中找出字典序最大的字符串 I
3403. 从盒子中找出字典序最大的字符串 I 题目链接:3403. 从盒子中找出字典序最大的字符串 I 代码如下: class Solution { public:string answerString(string word, int numFriends) {if (numFriends 1) {return word;}string res;for (int i 0;i &…...

全志A40i android7.1 调试信息打印串口由uart0改为uart3
一,概述 1. 目的 将调试信息打印串口由uart0改为uart3。 2. 版本信息 Uboot版本:2014.07; Kernel版本:Linux-3.10; 二,Uboot 1. sys_config.fex改动 使能uart3(TX:PH00 RX:PH01),并让boo…...
Hive 存储格式深度解析:从 TextFile 到 ORC,如何选对数据存储方案?
在大数据处理领域,Hive 作为 Hadoop 生态中重要的数据仓库工具,其存储格式的选择直接影响数据存储成本、查询效率和计算资源消耗。面对 TextFile、SequenceFile、Parquet、RCFile、ORC 等多种存储格式,很多开发者常常陷入选择困境。本文将从底…...
【无标题】路径问题的革命性重构:基于二维拓扑收缩色动力学模型的零点隧穿理论
路径问题的革命性重构:基于二维拓扑收缩色动力学模型的零点隧穿理论 一、传统路径模型的根本缺陷 在经典正方形路径问题中(图1): mermaid graph LR A((A)) --- B((B)) B --- C((C)) C --- D((D)) D --- A A -.- C[无直接路径] B -…...
Mysql8 忘记密码重置,以及问题解决
1.使用免密登录 找到配置MySQL文件,我的文件路径是/etc/mysql/my.cnf,有的人的是/etc/mysql/mysql.cnf 在里最后加入 skip-grant-tables重启MySQL服务 service mysql restartShutting down MySQL… SUCCESS! Starting MySQL… SUCCESS! 重启成功 2.登…...
Redis:现代应用开发的高效内存数据存储利器
一、Redis的起源与发展 Redis最初由意大利程序员Salvatore Sanfilippo在2009年开发,其初衷是为了满足他自己的一个项目需求,即需要一个高性能的键值存储系统来解决传统数据库在高并发场景下的性能瓶颈。随着项目的开源,Redis凭借其简单易用、…...

免费数学几何作图web平台
光锐软件免费数学工具,maths,数学制图,数学作图,几何作图,几何,AR开发,AR教育,增强现实,软件公司,XR,MR,VR,虚拟仿真,虚拟现实,混合现实,教育科技产品,职业模拟培训,高保真VR场景,结构互动课件,元宇宙http://xaglare.c…...