当前位置: 首页 > article >正文

C++的异步相关操作

目录

一,认识同步与异步

1-1,同步

1-2,异步

二,future

2-1,future介绍

2-2,async函数模板

2-3,packaged_task类模板

2-4,promise类模板


一,认识同步与异步

        同步和异步是处理任务执行顺序的两种不同方式。

1-1,同步

        同步操作意味着任务按顺序执行,一个任务完成后才会开始下一个任务。在同步编程模型中,调用者会等待被调用者完成操作后再继续执行,如单一执行流完成一个具体任务。

特点:

  1. 顺序执行:任务按照调用顺序依次执行。
  2. 阻塞调用:调用者会阻塞,直到被调用者完成操作。
  3. 易于理解和调试:代码逻辑简单明了,因为任务按顺序执行。

1-2,异步

        异步操作意味着任务可以并行执行,调用者不需要等待被调用者完成操作即可继续执行。异步编程模型通常使用回调函数、多线程或线程池来处理。

特点:

  1. 并行执行:任务可以并行执行,提高程序效率。
  2. 非阻塞调用:调用者不会阻塞,继续执行其他任务。
  3. 复杂性增加:代码逻辑可能变得复杂。

二,future

2-1,future介绍

        future是C++11标准库中的⼀个模板类,它表示⼀个异步操作的结果,即保存一个异步任务的结果。它本质不是一个异步任务,而是一个辅助我们获取异步任务结果的东西。通过使用future,我们可以实现线程之间的同步,确保任务完成后再获取结果并继续执行后续操作。

        当我们在多线程编程中使用异步任务时,future可以帮助我们在需要的时候获取任务的执行结果。future的⼀个重要特性是能够阻塞当前线程,直到异步操作完成,从而确保我们在获取结果时不会遇到未完成的操作。

future这里常用的成员函数get():获取异步操作的结果。如果异步操作尚未完成,get方法会阻塞当期线程,直到结果可用返回。

        注意:future只是提供了一种安全的方式来获取异步任务的结果,如:使用future::get()函数来获取任务的结果,此函数会阻塞当前线程,直到异步操作完成。它不能单独使用,需要搭配一些能够执行异步任务的模板类或函数作为返回值一起使用。future对象通常由async、packaged_task、promise方式创建,它们三者都运用了多线程相关的库,g++编译时需链接。

2-2,async函数模板

        在C++中,async 是标准库<future>头文件中提供的一个函数模板,用于异步执行任务。它允许你在不阻塞当前线程的情况下启动一个新任务,并在稍后获取其结果。async 函数返回一个 future 对象,该对象表示异步操作的结果。

async的第一个参数:一个可选的启动策略,它决定了异步任务是如何被执行的。该参数有下面两种选择:

        launch::async:异步执行。它会在内部创建一个线程,任务会在该线程中运行。

        launch::deferred:同步执行。任务不会立即运行,直到future的get或wait方法去获取结果时才会被调用。

        默认情况下,如果不指定启动策略,它会选择最适合的策略,通常是launch::async | launch::deferred。

async的后续参数:后续参数是要异步执行的函数及其参数。可以是函数指针、function、Lambda表达式或可调用对象。

#include <iostream>

#include <future>

using namespace std;

int Add(int num1, int num2)

{

    cout << "Add()" << endl;

    return num1 + num2;

}

int main()

{

    // launch::async策略:内部创建一个线程执行函数,函数运行结果通过future获取

    // launch::deferred策略:同步策略,获取结果的时候再去执行任务

    future<int> res = async(launch::async, Add, 11, 22);

    cout << "--------------------------" << endl;

    cout << res.get() << endl;

    return 0;

}

2-3,packaged_task类模板

        packaged_task是C++11一个将可调用对象(如函数、lambda表达式或函数对象)包装为异步任务的类。它提供了一种将可调用对象(如函数、lambda 表达式、函数对象等)封装起来后放到其它线程中去异步执行。

#include <iostream>

#include <future>

#include <thread>

#include <memory>

using namespace std;

int Add(int num1, int num2)

{

    cout << "Add()" << endl;

    return num1 + num2;

}

int main()

{

    // 封装任务

    auto task = make_shared<packaged_task<int(int, int)>>(Add);

    // 获取任务包关联的future对象

    future<int> res = task->get_future(); // get_future()用于获取关联的future对象

    // 在另一个线程中异步执行封装的任务

    thread thr([task](){ (*task)(11, 22); });

    cout << "--------------------------" << endl;

    // 获取结果

    cout << res.get() << endl;

    thr.join();

    return 0;

}

2-4,promise类模板

        C++中的promise是一个类模板,与packaged_task不同的是,promise是对任务结果的封装。使用时,它实例化的对象返回一个future后,就开始在其它线程中向promise对象设置数据,而其它线程的关联future就可以获取数据。

#include <iostream>

#include <future>

#include <thread>

#include <memory>

using namespace std;

int Add(int num1, int num2)

{

    cout << "Add()" << endl;

    return num1 + num2;

}

int main()

{

    // 在使用的时候,先实例化一个指定结果的promise对象

    promise<int> pro;

    // 通过promise对象,获取关联的future对象

    future<int> res = pro.get_future(); // get_future()用于获取关联的future对象

    // 给promise设置数据,这样可以通过关联的future获取到这个设置的数据了

    thread thr([&pro](){

        int sum = Add(11 , 22);

        pro.set_value(sum); // 设置promise的值,并使与之关联的future对象进入就绪状态

    });

    cout << res.get() << endl;

    thr.join();

    return 0;

}


http://www.kler.cn/a/561544.html

相关文章:

  • 信创终端上如何将PDF文件转为OFD文件
  • [java基础-JVM篇]2_垃圾收集器与内存分配策略
  • 从DeepSeek大爆发看AI革命困局:大模型如何突破算力囚笼与信任危机?
  • 量子计算的基本运算:Hadamard 门、CNOT 门、Pauli 门详解
  • 深度学习进阶:构建多层神经网络
  • Vue 3的Proxy比Vue 2的Object.defineProperty有哪些优势?
  • 和Claude对战黑白棋!一起开发AI对弈游戏
  • C++复习专题——泛型编程(模版),包括模版的全特化和偏特化
  • 基于Springboot银行信用卡额度管理系统【附源码】
  • 广州千叶凭借多元化泳池设备,为福州文旅泳池筑就优渥水环境
  • 【ECMAScript6】
  • Hbase使用shell命令语句大全
  • css文本两端对齐
  • C语言 —— 此去经年 应是良辰好景虚设 - 函数
  • GCC 和 G++的基本使用
  • 最新前端框架选型对比与建议(React/Vue/Svelte/Angular)
  • 【qt链接mysql】
  • Android BLE 的扫描配对、连接流程梳理
  • 【C++】:STL详解 —— vector类
  • Seata分布式事务【详解分布式事务AT模式、2PC两阶段提交协议、Seata Server(TC)环境搭建,附有示例+代码】