C++异步(1)

什么是异步?

异步就是多个线程是同时执行的,与之相对的就是线程同步,二者都应用在并发的场景上。

异步的特点

异步执行的任务无需等待其他任务完成,其本身是通过非阻塞的方式执行的,不依赖前驱任务,通常用于IO密集型场景。

非阻塞:线程不会被其他线程阻塞;

回调或事件驱动:

1、可以通过最直接采用策略执行回调函数,自动创建和管理线程;

2、还可以通过primise收到那个执行线程设置future的异步结果;

未来类--future

future简单来说就是存储线程结果的一个模版类,我们可以通过其get方法获取其异步编程结果的值;

async策略

执行策略:launch::async代表的是立刻在当前线程处执行异步回调函数;

cpp 复制代码
//执行线程回调函数
double func(){
    cout<<"我是线程回调函数"<<endl; 
    return 6.6;
}

void testfuture(){
    future<double> ret=async(launch::async,func);//立即执行的策略
    cout<<"开始睡眠"<<endl;
    sleep(2);
    auto res=ret.get();
    cout<<"future:"<<res<<endl; 
}

其中ret接收的就是异步线程回调函数的返回值;

deferred策略

该执行策略代表的是延迟执行,也就是主线程执行到async函数时不会立刻触发执行异步回调函数,而是在后续调用future的get方法时才会触发执行回调函数;

cpp 复制代码
#pragma once 
#include <future>
#include <iostream>
#include <unistd.h>
using namespace std; 



//执行线程回调函数
double func(){
    cout<<"我是线程回调函数"<<endl; 
    return 6.6;
}


void testfuture2(){
    future<double>ret=async(launch::deferred,func);//延迟执行策略
    cout<<"开始睡眠"<<endl;
    sleep(2);
    auto res=ret.get();

    cout<<"future:"<<res<<endl; 
}

这段程序的执行结果就是先打印"开始睡眠",然后睡眠2s,执行到get处,才执行回调函数,打印"我是线程回调函数",返回res获取返回值6.6,最后打印"future:6.6";

Promise(承诺未来值)

Promise也是一个模版类,通常配合future使用,用于在线程间传递数据同步异步操作的结果

解决的问题

(1) 线程间结果的传递
  • 普通线程函数只能通过参数传递输入数据,但无法直接返回计算结果(除非使用全局变量或指针,但这不够安全)。

  • promise 提供了一种安全、标准化的方式 ,让一个线程(生产者)可以设置一个值,而另一个线程(消费者)可以通过 future 获取这个值。

(2) 异步操作的同步
  • 在异步编程中,我们可能需要等待某个线程完成任务并获取其结果,而 promise/future 提供了一种线程安全的等待机制,避免了手动使用条件变量或锁。
(3) 异常传递
  • 如果一个线程在执行过程中抛出异常,可以通过 promise 将异常传递给 future,让调用方能够捕获并处理它。

实现方案

promise+move

cpp 复制代码
#include <iostream>
#include <future>
#include <thread>

using namespace std;

void task(promise<int> pro) {
	pro.set_value(666);
}


int main() {
	promise<int>ff;
	//绑定future和promise
	future<int>fut = ff.get_future();
	thread t(task,move(ff));
	//获取结果
	cout <<"异步future:"<< fut.get() << endl;
	t.join();

	return 0;
}

这种方案是比较安全的,因为没有使用指针和引用,关键点在于,中间变量作为参数,回调执行完就会释放掉参数pro;

那么问题来了,回调执行完就会释放掉pro,那future还能获取结果吗?

答案是可以的!future从promise读取结果的过程在于set_value写入,执行回调之前future和prommise已经绑定了共享的关系,而set_value就会同步数据给future;即便是后续参数pro和主线程的ff都无效了,future依旧可以获取到正确的结果;

promise+ref

cpp 复制代码
#include <iostream>
#include <future>
#include <thread>

using namespace std;

void task(promise<int>& pro) {
	pro.set_value(666);
}


int main() {
	promise<int>ff;
	//绑定future和promise
	future<int>fut = ff.get_future();
	thread t(task,ref(ff));
	//获取结果
	cout <<"异步future:"<< fut.get() << endl;
	t.join();

	return 0;
}

与上面的区别在于回调的参数是引用,而是实参需要使用ref强调传递的是引用对象,这种方法因涉及引用,所以没有使用move安全一些;

性能分析:

相关推荐
CodeCraft Studio4 小时前
3D文档控件Aspose.3D实用教程:使用 C# 构建 OBJ 到 U3D 转换器
开发语言·3d·c#·3d渲染·aspose·3d文件格式转换·3d sdk
superlls4 小时前
(Redis)主从哨兵模式与集群模式
java·开发语言·redis
让我们一起加油好吗4 小时前
【基础算法】初识搜索:递归型枚举与回溯剪枝
c++·算法·剪枝·回溯·洛谷·搜索
郝学胜-神的一滴4 小时前
Horse3D游戏引擎研发笔记(七):在QtOpenGL环境下,使用改进的Uniform变量管理方式绘制多彩四边形
c++·3d·unity·游戏引擎·图形渲染·虚幻·unreal engine
chenglin0165 小时前
C#_gRPC
开发语言·c#
骑驴看星星a5 小时前
数学建模--Topsis(Python)
开发语言·python·学习·数学建模
2401_876221346 小时前
Reachability Query(Union-Find)
c++·算法
tju新生代魔迷7 小时前
C语言宏的实现作业
c语言·开发语言
yueyuebaobaoxinx7 小时前
MATLAB 与 Simulink 联合仿真:控制系统建模与动态性能优化
开发语言·matlab·性能优化
躲着人群8 小时前
次短路&&P2865 [USACO06NOV] Roadblocks G题解
c语言·数据结构·c++·算法·dijkstra·次短路