跳转到主内容
新派编程网 - 新潮编程理念,全新技术课堂!

c++中如何使用std::future和std::promise_c++线程间数据传递【详解】

std::future 和 std::promise 是 C++11 提供的单次值传递同步机制,用于异步任务结果传递;std::promise 设置值,std::future 获取值,二者配对且仅能各操作一次,不可拷贝,需配合移动语义使用。 std::future 和 std::promise 是 C++11 引入的、用于在线程间**单次传递一个值**的 同步机制 。它们不是通用消息队列,也不是替代
std::mutex
的工具,而是专为“我启动一个 异步任务 ,稍后取它的返回值”这种场景设计的。 std::promise 和 std::future 必须配对使用,且只能消费一次 一个
std::promise
对象持有一个可写入的共享状态;调用
set_value()
(或
set_exception()
)后,其关联的
std::future
就能通过
get()
读取结果。关键约束是:
std::future::get()
只能调用一次,第二次会抛出
std::future_error
(错误码为
std::future_errc::no_state
或
std::future_errc::future_already_retrieved
)
std::promise::set_value()
也只能调用一次;重复调用会终止程序(
std::terminate
)
std::promise
和
std::future
之间通过移动语义转移共享状态,不能拷贝 常见误用:在多个线程里反复调用
get()
试图“轮询”,这会导致崩溃或未定义行为。 如何在线程间安全传递 int 值(最简可行示例) 典型模式是主线程创建
std::promise
,把它的
std::future
移交给工作线程(或反过来),再由某一方负责设置值、另一方负责获取。注意:
std::promise
本身不带线程安全保证,但它的
set_*
成员函数是线程安全的;
std::future::get()
是线程安全的阻塞等待。 立即学习 “ C++免费学习笔记(深入) ”; C函数速查手册(CHM版) C函数速查手册(CHM版) 下载
int main() { std::promise p; std::future f = p.get_future(); // 此处转移共享状态 std::thread t([&p]() { std::this_thread::sleep_for(std::chrono::seconds(1)); p.set_value(42); // 工作线程设置值 }); int result = f.get(); // 主线程阻塞等待并取值(自动 move) t.join(); return result; }
std::packaged_task 是更自然的封装方式 手动管理
std::promise
容易出错,尤其当你要传函数对象时。
std::packaged_task
把可调用对象和配套的
std::promise
绑定在一起,构造时自动生成
std::future
,调用时自动触发
set_value()
: 适用于“异步执行一个函数,并取其返回值”场景 支持 lambda、函数指针、成员函数等所有可调用类型 避免手动调用
set_value()
,减少逻辑遗漏风险
int main() { std::packaged_task task([]{ return 123; }); std::future f = task.get_future(); std::thread t(std::move(task)); int x = f.get(); // 阻塞直到线程执行完 task 并返回 t.join(); return x; }
不要用 future/promise 替代线程安全容器或信号量 它不解决多生产者、多消费者、重复读写、流式数据等问题。例如: 想让线程 A 不断往缓冲区 push 数据,线程 B 不断 pop → 用
std::queue
+
std::mutex
+
std::condition_variable
想通知线程 B “事件发生了”,但不传具体值 → 用
std::atomic
或
std::condition_variable
想跨线程传字符串、vector 等大对象 → 注意移动语义,
std::future::get()
返回的是右值引用,会自动 move 最常被忽略的一点:future 的阻塞等待(
get()
、
wait()
)无法被中断,也没有超时重试的默认机制——如果 promise 永远不被 set,线程就永远卡住。生产环境务必配合
wait_for()
或
wait_until()
使用。

相关文章