C++11并发与多线程总结(七) -- std::async异步任务与std::future

文章目录

(一) 线程概念、创建及传参
(二) 独占互斥锁–mutex,lock_guardy与其他mutex
(三) unique_lock替换lock_guardy
(四) 单例模式(Singleton)下的线程安全问题
(五) window临界区
(六) condition_variable条件变量
(七) std::async异步任务与std::future< >
(八) packaged_task< >与promise< >
(九) 原子操作atomic<>简介

(1)简介

std::async一般与std::future< >配套使用,前者异步或同步调用一个函数,返回一个future的模板类对象,在future中可以拿到入口函数的返回值


(2)std::async

1.async异步调用函数,即创建一个线程,返回一个future模板类
2.async使用方式同thread 也可传入类函数(记住前面加&)
3.第一参数可以传入 std::launch::deferred标记,即延迟调用,等到get()才调用,且不创建线程,直接在主线程中执行(id一样),若不调用get或wait则不执行
4.不传入则默认是 std::launch::async | std::launch::deferred,则可能同步或异步
5.std::launch::async强制异步任务创建新线程,若系统资源紧张则通过thread创建失败导致崩溃
6.传入位或 (即同4)相当于开启两个标志位,是否开启线程或延迟由系统判定

  1. 使用方法
  • 简单的异步调用函数,参数传入方法同thread创建,一般会创建线程执行,使用future获取返回结果
  • get()获取结果若异步调用未结束则堵塞主线程
  • 若不调用get主线程结束,异步任务未结束则主线程结束后等待,可能出现问题
int mythreadfuntion(int num)
{
	cout << "mythreadfuntion异步执行 thread_id =" << this_thread::get_id() << endl;

	std::chrono::milliseconds time(3000); //三秒钟
	std::this_thread::sleep_for(time); //线程休眠

	cout << "mythreadfuntion结束执行 thread_id =" << this_thread::get_id() << endl;

	return num * 10;
}

std::future<int> result = std::async(mythreadfuntion,6); //创建一个线程开始执行返回值为int的参数传入6的mythreadfuntion

std::cout << "main主函数继续执行 " << endl;  //不会堵塞主函数

std::cout << "async获取结果: result.get = " << async_result.get() << endl; //获取结果,若函数还没执行结束则堵塞
  1. 传入参数std::launch::deferred
  • 以上使用方法不传入第一参数,若第一参数传入std::launch::deferred则表示延迟执行,即不创建线程,直到执行到future的get函数才开始执行,且在主线程中执行
	std::future<int> async_result = std::async(std::launch::deferred,mythreadfuntion, 6); //直接在主线程中执行(id一样),若不调用get或wait则不执行

	std::cout << "main主函数继续执行 " << endl;
		//result.wait(); //调用也会wait堵塞
	std::cout << "async获取结果: result.get = " << async_result.get() << endl;  //到此才调用mythreadfuntion
  1. 传入参数std::launch::async
  • 效果同1
  1. async与thread区别

     	thread强制创建新线程,若资源紧张则创建失败
     	thread不方便获取入口函数的返回值,可使用全局函数或 packaged_task获取
    
     	async创建异步任务,有系统判定是否可用创建线程,若不可以则在当前调用线程执行
     	async若延迟任务,线程中没有使用get或wait则不调用入口函数
     	async可用使用future.wait_for(3s)对任务状态进行判断
     	async可用future对入口函数返回值进行获取
    
     	线程数量最好控制在100-200
    

(3)std::future< >

1.用于访问异步数据,即将来的数据
2.调用get()或wait()则等待子线程执行完才返回
3.不能多次调用get(),只能调用一次,除非用future_share
4.调用wait_for返回一个包含 超时,延迟,就绪三种枚举类型std::future_status
5.若async传入deferred,wait_for传入时间无效,程序不会等待,进入次调用get才执行函数
6.std::chrono::seconds(1)传入wait_for等待时长
7.vaile()返回一个布尔值,判定里面是否存在有效值

  1. wait_for的使用
  • 传入参数是std::chrono::seconds(int)时间(或 1s),返回值是枚举类型std::future_status,包含超时,就绪,延迟三种状态,用来判断async线程调用的状态
  • 超时则线程为执行结束
  • 就绪即可获取函数返回值
  • 延迟则延迟执行,此时可调用get()让其执行后返回
	std::future<int> result = std::async(mythreadfuntion, 6); //创建一个线程开始执行

	std::cout << "main主函数继续执行 " << endl;

	std::future_status s = result.wait_for(std::chrono::seconds(1)); //返回一个枚举类型enum

	if(s == future_status::timeout) //wait_for 1秒时超时
		std::cout << "wait_for等待超时 " << endl;
	else if(s == future_status::ready) //wait_for 4秒时准备
		std::cout << "wait_for准备就绪" << endl;
	else if (s == future_status::deferred) //async传入deferred且程序不会等待,进入次调用get才执行函数
		std::cout << "wait_for延迟" << endl;


(4)std::share_future< >

1.future由于get()不是复制赋值,而是值的移动,所以只能调用一次,调用后则已被清空
2.使用future创建shared_future两种方式
一种std::shared_future result_s (std::move(result));
另一种std::shared_future result_s (result.share());
3.用get()获取值,可以调用多次

	std::shared_future<int> result_s;
	if(result.valid())     //判断是否有有效值
		result_s = result.share(); //创建共享

	std::cout << "async获取结果: result_s.get = " << result_s.get() << result_s.get() << endl; //调用get则堵塞,若注释此句主函数将继续执行,但不会退出(可能不安全)


  • 测试代码
#include <iostream>
#include<thread>
#include<mutex>
#include <future>

using namespace std;

int mythreadfuntion(int num)
{
	cout << "mythreadfuntion异步执行 thread_id =" << this_thread::get_id() << endl;

	std::chrono::milliseconds time(3000); //三秒钟
	std::this_thread::sleep_for(time); //线程休眠

	cout << "mythreadfuntion结束执行 thread_id =" << this_thread::get_id() << endl;

	return num * 10;
}

int main()
{
	std::cout << "main主函数id = " << this_thread::get_id() << endl;

	std::future<int> result = std::async(mythreadfuntion, 6); //创建一个线程开始执行

	std::cout << "main主函数继续执行 " << endl;

	std::future_status s = result.wait_for(std::chrono::seconds(1)); //返回一个枚举类型enum

	if(s == future_status::timeout) //wait_for 1秒时超时
		std::cout << "wait_for等待超时 " << endl;
	else if(s == future_status::ready) //wait_for 4秒时准备
		std::cout << "wait_for准备就绪" << endl;
	else if (s == future_status::deferred) //async传入deferred且程序不会等待,进入次调用get才执行函数
		std::cout << "wait_for延迟" << endl;

	std::shared_future<int> result_s;
	if(result.valid())     //判断是否有有效值
		result_s = result.share(); //创建共享

	std::cout << "async获取结果: result_s.get = " << result_s.get() << result_s.get() << endl; //调用get则堵塞,若注释此句主函数将继续执行,但不会退出(可能不安全)

	std::cout << "main主函数结束 " << endl;
}

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
是的,C++ 11 引入了 std::async 函数,可以用它来创建异步任务std::async 函数的原型如下所示: ```c++ template <class Function, class... Args> std::future<typename std::result_of<Function(Args...)>::type> async(Function&& f, Args&&... args); ``` std::async 函数的作用是创建一个异步任务,并返回一个 std::future 对象,用于获取异步任务的返回值。std::async 函数的第一个参数是要执行的函数,后面的参数是该函数的参数。该函数会在一个新线程中执行,并在执行完成后返回结果。如果该函数抛出异常,则 std::future 对象中会保存该异常信息。 std::async 函数还可以指定执行策略,例如 std::launch::async 表示在新线程中执行异步任务std::launch::deferred 表示在调用 std::future::get() 函数时执行异步任务。如果不指定执行策略,则由编译器自行决定。 以下是一个使用 std::async 函数创建异步任务的示例: ```c++ #include <iostream> #include <future> int foo(int x) { std::cout << "foo is running in thread " << std::this_thread::get_id() << std::endl; return x + 1; } int main() { std::future<int> result = std::async(std::launch::async, foo, 1); std::cout << "main is running in thread " << std::this_thread::get_id() << std::endl; std::cout << "result is " << result.get() << std::endl; return 0; } ``` 在上面的示例中,使用 std::async 函数创建了一个异步任务 foo,并将参数 1 传递给该函数。执行结果会保存在 std::future 对象中,可以使用 std::future::get() 函数获取异步任务的返回值。在主线程中也输出了一些信息,用于对比异步任务和主线程中的执行情况。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值