当尝试回答另一个Stackoverflow问题时,我意识到这个简单的C ++ 11代码段隐式阻塞了调用线程:
std::async(std::launch::async, run_async_task)
在我看来,这似乎是规范的C ++ 11异步启动任务而不关心结果的方法。而是一个有明显显式地创建和分离线程(见答案所提到的问题),以实现这一目标。
所以这是我的问题:在安全性/正确性方面,是否有任何原因std::future
必须阻止a的析构函数?如果get
仅阻塞则不足够,否则,如果我对返回值或异常不感兴趣,那简直就是开枪而忘了吗?
阻止std :: async和线程返回的期货的析构函数:这是一个有争议的话题。以下按时间顺序排列的论文清单反映了委员会成员的一些讨论:
尽管进行了很多讨论,但是对于C ++ 14,没有计划对std :: future和std :: thread的析构函数的阻塞行为进行任何更改。
关于您的问题,最有趣的论文可能是汉斯·勃姆(Hans Boehm)的第二篇。我引用一些部分来回答您的问题。
[..]
async()
使用async
启动策略返回的期货在其析构函数中等待关联的共享状态准备就绪。这样可以防止关联线程继续运行,并且不再有等待它完成的方法,因为关联的未来已被破坏。无需英勇的努力来等待完成,这样的“失控”线程可以继续运行超过它所依赖的对象的生存期。[例子]
最终结果可能是跨线程“内存粉碎”。这个问题当然是可以避免的,如果
get()
还是wait()
被称为[..]他们[期货]被破坏之前。困难[..]是意外的异常可能导致该代码被绕过。因此,通常需要某种示波器来确保安全。如果程序员忘记添加范围保护,则攻击者很可能会在适当的时候生成例如bad_alloc异常,以利用监督的优势,并导致堆栈被覆盖。也有可能控制用于覆盖堆栈的数据,从而获得对该过程的控制。根据我们的经验,这是一个足够细微的错误,在实际代码中很可能会忽略它。
更新:黄贯中的《旅行报告》还包含一些有关2013年9月会议结果的有趣信息:
关于异步析构函数不应阻止的问题,我们进行了大量讨论。[..]得到唯一支持的唯一位置是[..]提出建议,除非从异步返回,否则将来的析构函数将不会阻塞,这使其成为一个明显的例外。[..]显著讨论后,我们试图进位的唯一部分是N3776,企图澄清的位置
~future
和~shared_future
不除了可能在异步的存在阻止。尝试按照C的方式发出弃用。弃用异步而不替换。这项议案实际上几乎是提出来的。但是[..]它甚至在到达手术台之前就死了。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句