首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >为什么` `std::async`返回的未来的析构函数会阻塞?

为什么` `std::async`返回的未来的析构函数会阻塞?
EN

Stack Overflow用户
提问于 2014-05-04 18:24:31
回答 1查看 11.4K关注 0票数 52

当我尝试回答另一个Stackoverflow question时,我意识到这个简单的C++11片段隐式地阻塞了调用线程:

代码语言:javascript
复制
std::async(std::launch::async, run_async_task)

对我来说,这似乎是一种规范的C++11方法,可以异步启动任务,而不关心结果。相反,为了实现这一点,人们必须显式地创建和分离线程(请参阅上述问题的answer )。

所以我的问题是:在安全性/正确性方面,std::future的析构函数必须阻塞吗?如果它只在get上阻塞,这还不够吗?否则,如果我对返回值或异常不感兴趣,它只是触发并忘记?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2014-05-05 02:39:25

阻塞std::async和线程:返回的期货的析构函数,这是一个有争议的话题。以下按时间顺序列出的文件反映了委员会成员的一些讨论:

尽管有很多讨论,但对于std::future和std::thread的析构函数的阻塞行为,C++14还没有计划的改变。

关于你的问题,最有趣的论文可能是汉斯·博姆的第二篇论文。我引用一些部分来回答你的问题。

。。使用async启动策略的async()返回的未来在其析构函数中等待关联的共享状态变为就绪。这可以防止关联线程继续运行,并且不再有等待线程完成的方法,因为关联的未来已被销毁。如果没有英雄式的努力来等待完成,这样的“失控”线程可以在它所依赖的对象的生命周期之后继续运行。

示例

最终的结果很可能是跨线程的“内存崩溃”。如果调用get()wait(),这个问题当然可以避免。在他们的未来被摧毁之前。困难的是..意外异常可能导致代码被绕过。因此,通常需要某种作用域保护来确保安全。如果程序员忘记添加作用域保护,攻击者很可能会在适当的时候生成bad_alloc异常,以利用该疏忽,并导致堆栈被覆盖。也可以控制用于重写堆栈的数据,从而获得对过程的控制。这是一个非常微妙的错误,在我们的经验中,它很可能在真实的代码中被忽略。

更新: Michael Wong的行程报告还包含了一些关于2013年9月会议结果的有趣信息:

关于异步析构函数不应该阻塞的问题,我们对此进行了大量的讨论。。。唯一得到相当多支持的职位是..建议未来的析构函数不会阻塞,除非从异步返回,这使它成为值得注意的异常。。。在重要的讨论之后,我们试图实现的唯一部分是N3776,试图澄清~future~shared_future不会阻止的位置,除非可能存在异步。有人试图发出类似于C的弃用命令。弃用异步而不进行替换。这项议案其实是差一点提出的。但是..。它甚至在到达手术台之前就死了。

票数 40
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/23455104

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档