0

0

C++中future和promise怎么用_C++多线程间值传递异步操作【并发】

尼克

尼克

发布时间:2026-02-05 14:41:02

|

192人浏览过

|

来源于php中文网

原创

future 和 promise 是用于线程间安全传递单个计算结果的异步通信工具,非线程启动机制;promise 单次写入、future 单次读取,通过共享状态关联,不可拷贝但可移动。

c++中future和promise怎么用_c++多线程间值传递异步操作【并发】

future 和 promise 是一对配合使用的异步通信工具

它们不是用来“启动线程”的,而是在线程之间安全传递单个计算结果的桥梁。一个线程用 promise 设置值,另一个线程用 future 等待并获取该值。核心约束是:每个 promise 只能调用一次 set_value()(或 set_exception()),否则抛出 std::future_error(错误码为 std::future_errc::promise_already_satisfied)。

  • std::promise 持有写权限,负责“发信号”;std::future 持有读权限,负责“收信号”
  • 两者通过共享状态(shared state)关联,通常由 promise.get_future() 获取对应 future
  • 不能拷贝 futurepromise,但可以移动(std::move
  • 如果 future 被析构而没人调用 get(),且 promise 未被满足,程序不会崩溃,但该结果永久丢失

如何避免 future.wait() 阻塞主线程

直接调用 future.wait() 会阻塞当前线程直到结果就绪,这在 GUI 或响应式系统中不可接受。更实用的方式是轮询或超时等待:

  • future.wait_for(std::chrono::milliseconds(10)) == std::future_status::ready 做非阻塞检测
  • future.wait_until(std::chrono::steady_clock::now() + std::chrono::seconds(2)) 设定绝对截止时间
  • 真正异步响应应结合 std::async 或手动线程 + 回调,future 本身不提供回调机制
  • 注意:wait_forwait_until 返回 std::future_status::timeout 时不抛异常,但后续调用 get() 仍会阻塞到就绪

promise.set_value() 必须在 shared state 销毁前调用

如果 promise 对象先于关联的 future 被销毁,且尚未调用 set_value()set_exception(),则其 shared state 进入“broken”状态。此时 future.get() 会立即抛出 std::future_error(错误码为 std::future_errc::broken_promise)。

  • 常见陷阱:把 promise 声明在局部作用域,又在线程中异步调用 set_value(),但主线程已退出作用域导致 promise 析构
  • 解决方法:将 promise 包装进 std::shared_ptr,确保生命周期覆盖异步写入过程
  • 或者改用 std::packaged_task,它自动管理 promise 生命周期,并可绑定到任意可调用对象

与 std::async 的关系:别混用,也别替代

std::async 内部封装了 promise/future,但它还负责线程调度和延迟策略(std::launch::asyncstd::launch::deferred)。你不能用 async 替代手动管理的 promise——比如无法从 async 返回的 future 反向拿到 promise 来设值。

塔猫ChatPPT
塔猫ChatPPT

塔猫官网提供AI一键生成 PPT的智能工具,帮助您快速制作出专业的PPT。塔猫ChatPPT让您的PPT制作更加简单高效。

下载

立即学习C++免费学习笔记(深入)”;

  • 需要“主动触发结果”的场景(如 I/O 完成、信号到达、用户输入),必须用 promise
  • 只需要“异步执行函数并取返回值”,优先用 std::async,简洁且不易出错
  • std::async 默认可能延迟执行(取决于实现和 flag),而手动 promise + 线程是完全可控的
  • 多个线程向同一个 future 写入?不行。一个 promise 只能有一个写入端,这是设计前提

最易被忽略的一点:shared state 的内存模型。即使你用 promise.set_value() 写入一个 int,它对 future.get() 的可见性由 future 的同步语义保证,不需要额外加 std::atomic 或锁——但如果你在 set_value() 前修改了外部变量,那些修改不一定对读线程可见,这点常被误认为是 future 的问题。

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
string转int
string转int

在编程中,我们经常会遇到需要将字符串(str)转换为整数(int)的情况。这可能是因为我们需要对字符串进行数值计算,或者需要将用户输入的字符串转换为整数进行处理。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

585

2023.08.02

int占多少字节
int占多少字节

int占4个字节,意味着一个int变量可以存储范围在-2,147,483,648到2,147,483,647之间的整数值,在某些情况下也可能是2个字节或8个字节,int是一种常用的数据类型,用于表示整数,需要根据具体情况选择合适的数据类型,以确保程序的正确性和性能。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

549

2024.08.29

c++怎么把double转成int
c++怎么把double转成int

本专题整合了 c++ double相关教程,阅读专题下面的文章了解更多详细内容。

153

2025.08.29

C++中int的含义
C++中int的含义

本专题整合了C++中int相关内容,阅读专题下面的文章了解更多详细内容。

204

2025.08.29

线程和进程的区别
线程和进程的区别

线程和进程的区别:线程是进程的一部分,用于实现并发和并行操作,而线程共享进程的资源,通信更方便快捷,切换开销较小。本专题为大家提供线程和进程区别相关的各种文章、以及下载和课程。

589

2023.08.10

Python 多线程与异步编程实战
Python 多线程与异步编程实战

本专题系统讲解 Python 多线程与异步编程的核心概念与实战技巧,包括 threading 模块基础、线程同步机制、GIL 原理、asyncio 异步任务管理、协程与事件循环、任务调度与异常处理。通过实战示例,帮助学习者掌握 如何构建高性能、多任务并发的 Python 应用。

279

2025.12.24

java多线程相关教程合集
java多线程相关教程合集

本专题整合了java多线程相关教程,阅读专题下面的文章了解更多详细内容。

21

2026.01.21

C++多线程相关合集
C++多线程相关合集

本专题整合了C++多线程相关教程,阅读专题下面的的文章了解更多详细内容。

23

2026.01.21

java中fail含义
java中fail含义

本专题整合了java中fail的含义、作用相关内容,阅读专题下面的文章了解更多详细内容。

0

2026.02.05

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
React 教程
React 教程

共58课时 | 4.6万人学习

Pandas 教程
Pandas 教程

共15课时 | 1万人学习

ASP 教程
ASP 教程

共34课时 | 4.5万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号