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