Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/135.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 为什么将来的析构函数是从'std::async'阻塞返回的?_C++_Multithreading_C++11_Asynchronous_Std - Fatal编程技术网

C++ 为什么将来的析构函数是从'std::async'阻塞返回的?

C++ 为什么将来的析构函数是从'std::async'阻塞返回的?,c++,multithreading,c++11,asynchronous,std,C++,Multithreading,C++11,Asynchronous,Std,在尝试回答另一个问题时,我意识到这个简单的C++11代码段隐式地阻止了调用线程: std::async(std::launch::async, run_async_task) 在我看来,这似乎是一种规范的C++11异步启动任务的方法,而不必关心结果。相反,为了实现这一点,显然必须显式地创建和分离线程(请参见上文提到的问题) 所以我的问题是:std::future的析构函数必须被阻塞,这与安全性/正确性有关吗?如果它只阻塞get,否则,如果我对返回值或异常不感兴趣,它只是简单地触发并忘记,这难道

在尝试回答另一个问题时,我意识到这个简单的C++11代码段隐式地阻止了调用线程:

std::async(std::launch::async, run_async_task)
在我看来,这似乎是一种规范的C++11异步启动任务的方法,而不必关心结果。相反,为了实现这一点,显然必须显式地创建和分离线程(请参见上文提到的问题)


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

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

  • 汉斯·博姆
  • 赫伯·萨特
  • 赫伯·萨特
  • 作者:赫伯·萨特、钱德勒·卡拉斯、尼古拉斯·古斯塔夫松
  • 汉斯·博姆
  • 作者:赫伯·萨特、钱德勒·卡拉斯、尼古拉斯·古斯塔夫松
  • 赫伯·萨特
  • 赫伯·萨特
虽然有很多讨论,但对于std::future和std::thread的析构函数的阻塞行为,C++14没有计划进行任何更改

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

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

[示例]

最终的结果很可能是一个跨线程的“内存崩溃”。如果在期货被销毁之前调用了
get()
wait()
,当然可以避免这个问题。难点[…]在于意外异常可能导致绕过该代码。因此,通常需要某种范围防护装置来确保安全。如果程序员忘记添加scope guard,攻击者可能会在适当的时候生成一个bad_alloc异常,以利用疏忽,并导致堆栈被覆盖。还可以控制用于覆盖堆栈的数据,从而获得对进程的控制。根据我们的经验,这是一个非常微妙的错误,在实际代码中很可能会被忽略

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

关于异步析构函数不应阻塞的问题,我们对此进行了大量讨论。[…]唯一得到大量支持的立场是[…]提出建议,未来的析构函数不会阻塞,除非从async返回,这是一个值得注意的例外。[…]经过重要讨论后,我们尝试采用的唯一部分是N3776,试图澄清以下立场:
~future
~shared_future
不会阻塞,除非可能存在异步。有人试图按照C.Deprecate async的思路发布一个弃用命令,而不进行替换。这项议案其实差不多已经提出了。但它甚至在到达手术台之前就死了


刚刚回复了你的评论,这里你有一个问题,关于这种行为有很多讨论。看看下面的文档:和@texasbruce:是的,因为它真的让我讨厌。我确信这是一种新的C++11y方式,我真的很惊讶地看到它被阻塞了,即使我不关心结果(只在最后的一个注释中提到)。除非有明确的必要,否则我认为它不是一个好的接口。我相信这是对c++14所做的修改之一,以实现您的预期。@W.B:好的一个建议是引入
then
方法,这样您就可以以异步方式组合未来。我希望他们也能在这一点上纠正这种行为。太好了,这正是我想要的答案!我仍然不相信这是一个正确的决定,但至少我现在清楚地看到了取舍。我猜这是RAII的一些极端形式,比如确保在析构函数中关闭文件处理程序。关于在C++14中修复这个问题,我觉得这个建议听起来像是:。或者至少它让您可以手动“分离”。我确信我已经看到了一些关于讨论结果的信息。现在我已经找到并更新了答案。虽然行为不会改变,但并发TS的
std::future::then()
看起来可以在这里使用。由
then
返回的
std::future
似乎不是同一种类型,因此如果它被销毁,则不需要阻止<代码>标准::异步([]{sleep(20);});返回从上面看不清楚,但是N3776进入了C++14。