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安全一些;

性能分析:

相关推荐
L_autinue_Star24 分钟前
手写vector容器:C++模板实战指南(从0到1掌握泛型编程)
java·c语言·开发语言·c++·学习·stl
元气小嘉1 小时前
前端技术小结
开发语言·前端·javascript·vue.js·人工智能
励志的大鹰哥1 小时前
V少JS基础班之第七弹
开发语言·javascript·ecmascript
AI360labs_atyun1 小时前
Java在AI时代的演进与应用:一个务实的视角
java·开发语言·人工智能·科技·学习·ai
凤年徐2 小时前
【数据结构与算法】203.移除链表元素(LeetCode)图文详解
c语言·开发语言·数据结构·算法·leetcode·链表·刷题
nbsaas-boot3 小时前
多租户架构下的多线程处理实践指南
java·开发语言·spring
无小道3 小时前
c++--typedef和#define的用法及区别
c语言·开发语言·汇编·c++
SoniaChen333 小时前
Rust基础-part2-变量和可变类型
开发语言·后端·rust
mit6.8243 小时前
[Vroom] 位置与矩阵 | 路由集成 | 抽象,解耦与通信
c++·人工智能·算法
ChuHsiang3 小时前
【C++】模板(二)
c++