std::future 相比于直接使用线程在 C++ 中有几个重要的优势,主要体现在同步结果获取简化代码管理、以及更安全的异步任务管理等方面。以下是 std::future 的一些主要优势:

1. 自动结果获取与同步

  • std::future 提供了一种便捷的机制来获取异步任务的返回值。当我们使用线程时,通常无法轻松获得线程的返回值,线程函数如果有返回值,需要通过共享变量、全局变量或其他同步机制进行通信,这使得代码更加复杂。

  • 通过 std::future,可以轻松获取异步任务的结果,它在内部同步管理任务执行的结果。

    例子:

    #include <iostream>
    #include <future> int compute() {
    return 42;
    } int main() {
    std::future<int> result = std::async(std::launch::async, compute);
    std::cout << "Result: " << result.get() << std::endl; // 自动等待线程完成并返回结果
    return 0;
    }

    在这种情况下,result.get() 会等待线程完成,并获取异步任务的返回值 42。这比直接使用线程共享状态的方式要简单得多。

2. 简化代码管理

  • 使用 std::thread 需要手动管理线程的生命周期,比如使用 join() 来等待线程执行完成。而 std::future 通过 get() 或者 wait() 来等待任务完成,自动管理同步,不需要手动调用 join()

    直接使用线程时:

    #include <iostream>
    #include <thread> void compute(int &result) {
    result = 42;
    } int main() {
    int result;
    std::thread t(compute, std::ref(result));
    t.join(); // 必须手动调用 join() 等待线程完成
    std::cout << "Result: " << result << std::endl;
    return 0;
    }

    这里要通过 std::ref(result) 共享数据,并且必须手动管理线程的结束 (join()),否则程序会发生错误。

3. 更安全的异步任务管理

  • std::futurestd::async 可以更好地管理异步任务,避免直接操作线程带来的错误。比如,当线程没有被正确 join 时,程序可能崩溃,而 std::future 会自动等待异步任务完成。

  • 如果程序异常退出或者忘记调用 join()std::thread 会导致程序中断或者未定义行为。而 std::future 不会发生这些问题,它通过 get() 自动等待异步任务完成。

    例如,如果使用 std::thread,忘记 join(),程序会出现崩溃风险:

    std::thread t([] { std::this_thread::sleep_for(std::chrono::seconds(1)); });
    // 如果没有 t.join(),程序将崩溃

4. 异常管理

  • std::future 可以捕获异步任务中的异常,而直接使用线程时,异常管理需要额外的工作。在 std::future 中,get() 不仅可以获取任务的结果,还可以在任务中出现异常时,将该异常抛出,方便后续处理。

    例子:

    #include <iostream>
    #include <future>
    #include <stdexcept> int faulty_task() {
    throw std::runtime_error("Something went wrong!");
    } int main() {
    std::future<int> result = std::async(std::launch::async, faulty_task);
    try {
    int value = result.get(); // 在此捕获异常
    } catch (const std::exception& e) {
    std::cerr << "Exception: " << e.what() << std::endl;
    }
    return 0;
    }

    直接使用 std::thread 时,要处理任务中的异常需要复杂的机制,std::future 简化了这一过程。

5. 延迟启动任务

  • 使用 std::asyncstd::future,你可以选择是否立即启动线程,或者延迟执行任务(惰性启动)。通过 std::async 的第二个参数(如 std::launch::deferred),可以控制任务是否异步执行或延迟执行,这种灵活性在直接使用线程时无法轻易实现。

    惰性启动:

    std::future<int> result = std::async(std::launch::deferred, compute); // 任务并不会立即执行
    // result.get() 执行时,任务才开始执行

总结

std::future 的主要优势在于:

  • 简化了异步任务的结果获取与同步操作;
  • 提供了更好的异常管理;
  • 避免了手动管理线程生命周期的复杂性;
  • 提供了延迟执行(deferred execution)的灵活性。

相比之下,std::thread 直接操作线程,虽然可以让程序员显式控制任务,但在实际开发中,这种显式控制常常导致复杂的代码管理和更大的错误风险,因此 std::future 是一种更高层次、更安全的选择。

`std::future`--异步的优势的更多相关文章

  1. C++11之std::future和std::promise

    为什么C++11引入std::future和std::promise?C++11创建了线程以后,我们不能直接从thread.join()得到结果,必须定义一个变量,在线程执行时,对这个变量赋值,然后执 ...

  2. C++11之std::future和std::promise和std::std::packaged_task

    为什么C++11引入std::future和std::promise?C++11创建了线程以后,我们不能直接从thread.join()得到结果,必须定义一个变量,在线程执行时,对这个变量赋值,然后执 ...

  3. C++并发高级接口:std::async和std::future

    std::async和std::future std::async创建一个后台线程执行传递的任务,这个任务只要是callable object均可,然后返回一个std::future.future储存 ...

  4. C++11 使用异步编程std::async和std::future

    先说明一点:std::asyanc是std::future的高级封装, 一般我们不会直接使用std::futrue,而是使用对std::future的高级封装std::async. 下面分别说一下. ...

  5. C++11 并发指南四(<future> 详解三 std::future & std::shared_future)

    上一讲<C++11 并发指南四(<future> 详解二 std::packaged_task 介绍)>主要介绍了 <future> 头文件中的 std::pack ...

  6. C++并发编程之std::async(), std::future, std::promise, std::packaged_task

    c++11中增加了线程,使得我们可以非常方便的创建线程,它的基本用法是这样的: void f(int n); std::thread t(f, n + 1); t.join(); 但是线程毕竟是属于比 ...

  7. C++并发编程之std::future

    简单地说,std::future 可以用来获取异步任务的结果,因此可以把它当成一种简单的线程间同步的手段.std::future 通常由某个 Provider 创建,你可以把 Provider 想象成 ...

  8. 【C++并发实战】(三) std::future和std::promise

    std::future和std::promise std::future std::future期待一个返回,从一个异步调用的角度来说,future更像是执行函数的返回值,C++标准库使用std::f ...

  9. C++11 并发指南四(<future> 详解三 std::future & std::shared_future)(转)

    上一讲<C++11 并发指南四(<future> 详解二 std::packaged_task 介绍)>主要介绍了 <future> 头文件中的 std::pack ...

  10. 第27课 “共享状态”及其管理者(std::future/std::shared_future)

    一. “共享状态” (一)“共享状态”对象 1. 用于保存线程函数及其参数.返回值以及新线程状态等信息.该对象通常创建在堆上,由std::async.std::promise和std::package ...

随机推荐

  1. .NET 中高效 Excel 解决方案 MiniExcel

    前言 MiniExcel 是一个用于 .NET 平台的轻量级.高性能的库,专注于提供简单易用的 API 来处理 Excel 文件.以下是 MiniExcel 的特点总结: 轻量级与高效:MiniExc ...

  2. CCF 有趣的数

    问题描述: 试题编号: 201312-4 试题名称: 有趣的数 时间限制: 1.0s 内存限制: 256.0MB 问题描述: 问题描述 我们把一个数称为有趣的,当且仅当: 1. 它的数字只包含0, 1 ...

  3. 暑假java自学进度总结03

    一.今日所学: 1.标识符命名规则: 必须: 1>由数字,字母,下划线,美元符组成: 2>不能以数字开头: 3>不能是关键字: 4>区分大小写: 建议: 1>命名方法,变 ...

  4. 关于android的图像视图的基本了解

    最好直接复制进去而不是拖进去 图片直接导入最好用小写字母命名,数字与字母之间要用_,而且数字好像不可以连用 centerInside,fitCenter,center的区别: centerInside ...

  5. 老旧 Linux 系统搭建现代 C++ 开发环境 —— 基于 neovim

    问题背景 公司配发的电脑是 macOS,日常开发需要访问 Linux 虚拟机,出于安全方面的考虑,只能通过跳板机登录.这阻止了大多数远程图形界面的使用,让写代码的工作变得复杂起来,市面上非常好用的 V ...

  6. 探索Amazon S3:存储解决方案的基石(Amazon S3使用记录)

    探索Amazon S3:存储解决方案的基石 本文为上一篇minio使用的衍生版 相关链接:1.https://www.cnblogs.com/ComfortableM/p/18286363 ​ 2.h ...

  7. 【C】Re11 剩下的笔记

    关于字符常量问题: #include <stdio.h> #include <stdlib.h> #include <string.h> void string01 ...

  8. Vue Vine:带给你全新的 Vue 书写体验!

    你好,我是 Kagol,个人公众号:前端开源星球. 上个月和 TinyVue 的小伙伴们一起参加了 VueConf 24 大会,有幸认识沈青川大佬,并了解了他的 Vue Vine 项目,Vue Vin ...

  9. Camera | 7.瑞芯微rk3568平台摄像头控制器MIPI-CSI驱动架构梳理

    因为有拍照.录制视频.直播等刚需,现在手机的摄像头基本都是高清,支持高清摄像头的SoC都支持MIPI-CSI. 不同SoC的MIPI-CSI在实现上有一定差别,即使同一厂家设计生产的芯片也都不尽相同. ...

  10. PG数据库导致断电/重启无法正常启动问题排查

    PG数据库导致断电/重启无法正常启动问题排查 一.问题 数据库断电后,启动PG数据库后无法正常启动,报"psql: could not connect to server: No such ...