未等待时重新赋值std::future的行为?C++代码相关疑问
关于std::future复用的技术问题
该函数设计用于在事务周期性开始后,异步执行一次lambda表达式:每次完成的事务都会调用该函数,仅在首次调用时启动异步操作。后续添加了重置功能,以便事务因故障停止后可“重新激活”函数,若事务再次启动,需再次异步执行lambda表达式。
对应的代码实现如下:
void first_trans(bool reset = false){ static bool ran_once{false}; static std::future<void> fut; if(reset) { ran_once = false; return; } if(!ran_once){ ran_once = true; // DO I NEED TO WAIT BEFORE THIS ASSIGNMENT // ON SUBSEQUENT ENTRIES TO THIS BLOCK? fut = std::async(std::launch::async, [=] { // do some stuff }); } }
参考的std::future赋值运算符文档说明:
赋值另一个future对象的内容。
- 释放任何共享状态,并将other的内容移动赋值给*this。赋值后,other.valid() == false,且this->valid()的值与赋值前other.valid()的值相同。
技术问题
- 赋值前是否必须等待std::future?现有代码能否正常运行,无重叠或泄漏问题?
- “被释放的”共享状态会发生什么?
问题解答
问题1:赋值前是否必须等待std::future?现有代码能否正常运行?
不需要提前等待,但要注意现有代码的潜在行为:
- 当对
fut执行赋值操作时,旧的std::future对象会被替换,其析构函数会被触发。对于由std::async(std::launch::async)创建的std::future,析构时会阻塞当前线程,直到关联的异步任务执行完毕。也就是说,如果第一次的异步任务还在运行时,触发重置后再次调用first_trans,当前线程会被阻塞,直到旧任务结束才会启动新的异步任务。 - 现有代码不会出现内存泄漏,共享状态会被正确释放;但如果业务要求新任务必须立即启动、不能等待旧任务,这种写法就不适用。如果允许等待旧任务完成后再启动新任务,现有代码可以正常运行,不会出现任务重叠执行的情况。
问题2:“被释放的”共享状态会发生什么?
当std::future释放共享状态时,分两种情况处理:
- 如果关联的异步任务已经完成:共享状态会直接被销毁,任务执行相关的资源(如结果存储、同步原语等)会被回收。
- 如果关联的异步任务仍在运行(针对
std::async(std::launch::async)创建的任务):std::future的析构函数会先阻塞等待任务执行完成,之后再销毁共享状态、释放所有相关资源。 - 本质上,共享状态的释放机制会保证异步任务的资源被正确回收,不会出现泄漏,但针对
std::async创建的异步任务,释放过程会等待任务结束。
内容的提问来源于stack exchange,提问作者ttemple
相关产品推荐
相关产品推荐

