C++怎么使用future和promise实现异步编程

来源:Vuejs社区作者:南京SEO公司头衔:草根站长
导读:本期聚焦于小伙伴创作的《C++怎么使用future和promise实现异步编程》,敬请观看详情,探索知识的价值。以下视频、文章将为您系统阐述其核心内容与价值。如果您觉得《C++怎么使用future和promise实现异步编程》有用,将其分享出去将是对创作者最好的鼓励。

C++标准库中的future和promise是异步编程的重要组件,二者配合可以实现线程间的结果传递和同步,不需要手动使用互斥锁和条件变量就能完成异步任务的结果获取。promise用于在一个线程中设置结果,future用于在另一个线程中获取这个结果,二者共享一个共享状态,结果设置后future就能感知到并获取对应值。

C++怎么使用future和promise实现异步编程

future和promise的基本概念

std::promise是一个模板类,用于在一个线程中存储一个值或者异常,这个值后续可以被关联的std::future对象获取。std::future同样是模板类,用于获取异步操作的结果,当结果还没有准备好时,调用future的get方法会阻塞当前线程,直到结果就绪。

二者的关联关系是通过std::promise::get_future方法建立的,调用这个方法会返回一个和当前promise关联的future对象,二者共享同一个共享状态,这个状态中存储了异步操作的结果或者异常信息。

基础使用示例

下面是一个最简单的使用示例,在主线程中创建promise,把关联的future传给子线程,子线程中通过promise设置结果,主线程通过future获取结果。

#include <iostream>
#include <future>
#include <thread>

// 子线程执行的函数,接收promise对象
void async_task(std::promise<int> prom) {
    // 模拟异步操作耗时
    std::this_thread::sleep_for(std::chrono::seconds(2));
    // 设置promise的结果
    prom.set_value(100);
}

int main() {
    // 创建promise对象,存储int类型结果
    std::promise<int> prom;
    // 获取关联的future对象
    std::future<int> fut = prom.get_future();
    
    // 启动子线程,传入promise对象,注意要使用std::move转移所有权
    std::thread t(async_task, std::move(prom));
    
    // 主线程获取结果,此时会阻塞直到子线程设置结果
    int result = fut.get();
    std::cout << "异步任务结果: " << result << std::endl;
    
    t.join();
    return 0;
}

传递异常的场景

如果异步操作中出现异常,也可以通过promise传递异常,future获取结果时会重新抛出这个异常,方便调用方处理错误情况。

#include <iostream>
#include <future>
#include <thread>
#include <stdexcept>

void async_task_with_exception(std::promise<int> prom) {
    try {
        // 模拟操作出现异常
        throw std::runtime_error("异步任务执行失败");
        prom.set_value(200);
    } catch (...) {
        // 捕获异常并设置到promise中
        prom.set_exception(std::current_exception());
    }
}

int main() {
    std::promise<int> prom;
    std::future<int> fut = prom.get_future();
    
    std::thread t(async_task_with_exception, std::move(prom));
    
    try {
        int result = fut.get();
        std::cout << "结果: " << result << std::endl;
    } catch (const std::exception& e) {
        std::cout << "捕获到异常: " << e.what() << std::endl;
    }
    
    t.join();
    return 0;
}

future的其他常用方法

除了get方法,future还有waitwait_for方法,用于等待结果就绪或者检查结果的就绪状态。

  • wait():阻塞当前线程,直到结果就绪,没有返回值。
  • wait_for(duration):阻塞当前线程一段时间,如果在指定时间内结果就绪,返回std::future_status::ready,否则返回std::future_status::timeout
  • wait_until(time_point):阻塞当前线程直到指定时间点,根据结果就绪情况返回对应的状态。

下面是一个使用wait_for的示例,避免无限阻塞:

#include <iostream>
#include <future>
#include <thread>
#include <chrono>

void long_task(std::promise<int> prom) {
    std::this_thread::sleep_for(std::chrono::seconds(3));
    prom.set_value(300);
}

int main() {
    std::promise<int> prom;
    std::future<int> fut = prom.get_future();
    
    std::thread t(long_task, std::move(prom));
    
    // 等待1秒,检查结果是否就绪
    auto status = fut.wait_for(std::chrono::seconds(1));
    if (status == std::future_status::ready) {
        std::cout << "结果已就绪: " << fut.get() << std::endl;
    } else if (status == std::future_status::timeout) {
        std::cout << "等待超时,结果还未就绪" << std::endl;
        // 继续等待或者做其他处理
        fut.wait();
        std::cout << "最终获取到结果: " << fut.get() << std::endl;
    }
    
    t.join();
    return 0;
}

使用注意事项

  1. promise对象只能调用一次set_value或者set_exception,重复调用会导致未定义行为。
  2. promise对象不能被拷贝,只能被移动,所以在传递给线程的时候需要使用std::move转移所有权。
  3. 如果promise对象在被销毁前没有设置结果,关联的future调用get的时候会抛出std::future_error异常,错误码是std::future_errc::broken_promise。
  4. future的get方法只能调用一次,重复调用会导致未定义行为,如果需要多次获取结果,可以使用std::shared_future。

shared_future的使用场景

如果有多个线程需要获取同一个异步任务的结果,可以使用std::shared_future,它可以被多个线程同时访问,get方法可以被多次调用。

#include <iostream>
#include <future>
#include <thread>
#include <vector>

void async_task(std::promise<int> prom) {
    std::this_thread::sleep_for(std::chrono::seconds(2));
    prom.set_value(400);
}

void consumer_task(std::shared_future<int> fut, int id) {
    int result = fut.get();
    std::cout << "消费者" << id << "获取到结果: " << result << std::endl;
}

int main() {
    std::promise<int> prom;
    std::future<int> fut = prom.get_future();
    // 转换为shared_future
    std::shared_future<int> shared_fut = fut.share();
    
    std::thread t(async_task, std::move(prom));
    
    // 启动多个消费者线程
    std::vector<std::thread> consumers;
    for (int i = 0; i < 3; i++) {
        consumers.emplace_back(consumer_task, shared_fut, i);
    }
    
    t.join();
    for (auto& c : consumers) {
        c.join();
    }
    
    return 0;
}

futurepromise异步编程C++多线程修改时间:2026-06-16 10:42:45

免责声明:​ 已尽一切努力确保本网站所含信息的准确性。网站内容多为原创整理与精心编撰,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们处理。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。