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

性能分析:

相关推荐
UpUpUp……42 分钟前
C++复习
开发语言·c++·笔记
BC的小新1 小时前
C++ Stack&Queue
c++
艾莉丝努力练剑1 小时前
深入详解编译与链接:翻译环境和运行环境,翻译环境:预编译+编译+汇编+链接,运行环境
c语言·开发语言·汇编·学习
charlie1145141911 小时前
从C++编程入手设计模式1——单例模式
c++·单例模式·设计模式·架构·线程安全
菠萝012 小时前
分布式CAP理论
数据库·c++·分布式·后端
开发者工具分享3 小时前
Lua 的速度为什么比 Python 快
开发语言·python·lua
蔗理苦3 小时前
2025-05-28 Python&深度学习8——优化器
开发语言·pytorch·python·深度学习·优化器
格子衫-20034 小时前
Java八股-Java优缺点,跨平台,jdk、jre、jvm关系,解释和编译
java·开发语言·jvm
Yurko134 小时前
【C语言】函数指针及其应用
c语言·开发语言·学习
zhifanxu4 小时前
Android开发常用Kotlin高级语法
android·开发语言·kotlin