讲师中心 微信公众号
AI工具推荐 视频效率加速

C++的std::promise和std::future如何实现线程间的一对一同步? (状态共享机制)

酷芳大大_4604

酷芳大大_4604

发布时间:2026-02-16 16:32:03

|

1012人浏览过

|

来源于php中文网

原创

std::promise与std::future需通过get_future()显式配对,一 promise 仅可绑定一 future;set_value()触发wait()/get()返回,get()只可调用一次,promise析构前未设置值则get()抛broken_promise。

c++的std::promise和std::future如何实现线程间的一对一同步? (状态共享机制)

std::promise 和 std::future 怎么配对传递值?

它们不是自动绑定的,必须通过 std::promise::get_future() 显式获取对应 std::future,且只能调用一次。一旦获取,std::promise 和 std::future 就共享底层状态对象(通常叫 __state 或类似实现细节),后续对 std::promise::set_value() 的调用会触发 std::future::wait() 或 std::future::get() 返回。

常见错误现象:std::future 构造后未从同一 std::promise 获取,或重复调用 get_future() —— 后者会抛出 std::future_error(错误码为 std::future_errc::future_already_retrieved)。

  • 一个 std::promise 只能关联一个 std::future;反之不成立(但多对一无意义,也不支持)
  • 不能把 std::promise 拷贝给另一个线程,它不可拷贝;必须移动(std::move(p))或用指针/智能指针传递
  • std::future 本身可移动,但移动后原对象变为无效状态(valid() == false)

为什么 set_value() 后 get() 不卡死,但 wait() 还要等?

因为 std::promise::set_value() 是“发信号”动作,它设置共享状态为 ready,并唤醒所有等待该状态的线程;而 std::future::get() 在返回前会隐式调用 wait(),再读取值 —— 所以它既同步又取值。但 wait() 只同步、不取值,适合只关心完成时机、不关心结果内容的场景(比如纯屏障)。

性能影响:如果值类型大且不需要立即使用,先 wait() 再 get() 可避免不必要的拷贝延迟(不过现代编译器常优化掉);若值小或必须立刻消费,直接 get() 更简洁。

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

C++14
C++14

C++14 对 C++11 的修正与增强版本,适合旧系统维护和较老工具链兼容。

下载
  • get() 只能调用一次,第二次会抛 std::future_error(std::future_errc::no_state)
  • 若 promise 被析构前未调用 set_value()、set_exception() 或 set_value_at_thread_exit(),则 future::get() 会抛 std::future_error(std::future_errc::broken_promise)
  • 不要在 promise 所在线程里直接调用 future::get() —— 它会永远阻塞,除非 promise 在另一线程中设置

std::promise 能用来做纯信号同步吗?

可以,而且很常用。当只需要通知“某事已完成”,不传数据时,std::promise<void></void> 配合 std::future<void></void> 是轻量级选择。它的 set_value() 不带参数,get() 返回 void,语义清晰。

容易踩的坑:有人误以为 std::future<void>.wait()</void> 等价于 std::condition_variable + std::mutex,其实不然——std::future<void></void> 不支持超时等待(wait_for/wait_until 是有的,但 void 版本仍受限于底层实现是否真正支持),且无法重置、无法多次通知。

  • 适合一次性同步点(如初始化完成、任务结束)
  • 不适用于需要多次触发、或需响应中断/超时的场景
  • 若需超时,必须用 std::future<t>::wait_for()</t>,但 void 类型下返回值仍是 std::future_status,不能忽略

跨线程传递 promise/future 时要注意什么?

核心是生命周期管理:promise 必须活到被 set_value() 调用之后,future 必须活到 get()/wait() 返回之后。最安全的方式是用 std::shared_ptr<:promise>></:promise> 包裹 promise,在生产者和消费者之间共享所有权;future 通常由消费者独占持有,无需共享。

典型错误:把局部 std::promise 对象 move 进线程函数,但主线程函数返回后 promise 被析构,子线程再调用 set_value() 就是未定义行为。

  • 推荐模式:在创建线程前 new 一个 std::promise,用 std::shared_ptr 管理;或直接用 std::packaged_task 替代手动配对
  • 避免裸指针传递 promise/future,尤其不要让多个线程同时写同一个 promise(set_value() 非线程安全,仅保证对同一 promise 的多次 set 是互斥的)
  • future 的 wait() 和 get() 是线程安全的,可被多个线程并发调用(但结果未定义:只有一个能成功取值,其余抛异常)

真正麻烦的从来不是怎么调用那几个函数,而是谁在什么时候销毁 promise、谁还在等着 future、以及有没有人忘了 set_value —— 这些问题不会报编译错误,但会让程序在某个负载下突然 hang 住或崩溃。

热门AI工具

更多
Seko
Seko Hot

一款AI视频创作工具,主要用于商汤科技推出的创编一体的AI短视频创作Agent,适合需要提升相关任务效率的用户。

咔片AIPPT

一款在线AI演示文稿制作工具,可根据主题和内容需求辅助生成PPT结构与页面,提高演示材料制作效率。

SkildArt
SkildArt Hot

SkildArt是一款AI文本写作工具,一站式 AI 视觉创作平台。

WorkBuddy

一款AI办公效率工具,主要用于腾讯云推出的AI原生桌面智能体工作台,适合需要提升相关任务效率的用户。

Laper
Laper Hot

Laper是专为编剧、导演和制片人推出的 AI 原生剧本创作工具。

Atoms
Atoms Hot

Atoms是一款AI智能体工具,第一支自动构建真实业务的 AI 团队。

豆包大模型

豆包大模型是一款由字节跳动推出的企业级大语言模型服务平台。

UpDream
UpDream Hot

一款AI视频创作工具,主要用于哔哩哔哩推出的自研AI视频创作工具,适合需要提升相关任务效率的用户。

DeepSeek

DeepSeek是一款面向对话、写作、编程和推理场景的AI大模型工具。

相关专题

更多
javascriptvoid(o)怎么解决
javascriptvoid(o)怎么解决

javascriptvoid(o)的解决办法:1、检查语法错误;2、确保正确的执行环境;3、检查其他代码的冲突;4、使用事件委托;5、使用其他绑定方式;6、检查外部资源等等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

636

2023.11.23

java中void的含义
java中void的含义

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

371

2025.11.27

C++ 智能指针与现代内存管理
C++ 智能指针与现代内存管理

深入讲解 C++ 现代内存管理的核心工具——智能指针,涵盖 unique_ptr 独占所有权语义、shared_ptr 引用计数机制与循环引用问题、weak_ptr 弱引用的应用场景、make_unique/make_shared 工厂函数的性能优势、自定义删除器的编写、RAII 资源管理思想的实践,以及从裸指针迁移到智能指针的重构策略,帮助开发者编写安全无泄漏的现代 C++ 代码。

359

2026.04.23

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

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

4298

2023.08.10

promise的用法
promise的用法

“promise” 是一种用于处理异步操作的编程概念,它可以用来表示一个异步操作的最终结果。Promise 对象有三种状态:pending(进行中)、fulfilled(已成功)和 rejected(已失败)。Promise的用法主要包括构造函数、实例方法(then、catch、finally)和状态转换。

4520

2023.10.12

html文本框类型介绍
html文本框类型介绍

html文本框类型有单行文本框、密码文本框、数字文本框、日期文本框、时间文本框、文件上传文本框、多行文本框等等。详细介绍:1、单行文本框是最常见的文本框类型,用于接受单行文本输入,用户可以在文本框中输入任意文本,例如用户名、密码、电子邮件地址等;2、密码文本框用于接受密码输入,用户在输入密码时,文本框中的内容会被隐藏,以保护用户的隐私;3、数字文本框等等。

4083

2023.10.12

Gradle插件开发入门教程
Gradle插件开发入门教程

本专题介绍Gradle插件开发的基本流程,涵盖插件类编写、自定义任务注册、扩展参数设计和插件应用方法,帮助你理解插件如何组织构建逻辑,减少多个项目之间的重复配置。

0

2026.10.22

Gradle Wrapper配置教程
Gradle Wrapper配置教程

本专题介绍Gradle Wrapper的基本作用,涵盖文件组成、生成方法、版本配置和任务调用,帮助你理解项目如何使用指定的Gradle版本,减少不同开发环境带来的构建差异。

0

2026.10.22

Golangci-lint检查器使用教程
Golangci-lint检查器使用教程

本专题整理Golangci-lint常用Linters的用途与配置方法,覆盖错误处理、无效代码、安全、复杂度、命名和依赖检查,帮助项目合理选规则。

0

2026.10.22

热门下载

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

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
C++ Core Guidelines
C++ Core Guidelines

共0课时 | 0人学习

C++ Reference
C++ Reference

共0课时 | 0人学习

C++ 官方标准说明
C++ 官方标准说明

共0课时 | 0人学习

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

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn