std :: list <std :: future>析构函数不会阻止</std :: future>

时间:2014-09-06 09:05:52

标签: c++ multithreading c++11 stdlist

我有一个多线程应用程序,循环等待用户输入作为主线程。 在正确的输入上,它应该停止循环并等待所有其他线程,以正确结束。

为此,我创建了一个 std :: list ,其中我为创建线程创建了 std :: future 对象

std::list<std::future<int>> threads;
threads.emplace_front(std::async(std::launch::async, ...));

我的印象是,让 list 超出范围,应该阻塞,直到所有线程返回其主函数,因为 list 的析构函数将会破坏所有 std :: future 元素和the destructor of those将等待,以便线程完成。

编辑:由于相关,我会在此处添加: 这是在Win7上使用Visual Studio 2013 Professional中的MSVC版本 的 /修改

当我尝试这个时,它没有阻止,我不得不添加

for (auto it = threads.begin(); it != threads.end(); ++it) {
    it->get();
}

到函数的末尾,要正确阻塞。

我是否错过了解某些内容,或者我是否必须以不同的方式创建该主题,以便做我想做的事情?

2 个答案:

答案 0 :(得分:13)

这是一个MSVC bug that has been fixed,但是在MS发布新版本的Visual C ++之前,修复程序将无法使用,可能在2015年的某个时候。(它也是available in the CTP for the new version,但是它很糟糕将其用于任何生产代码的想法...)

正如Scott Meyers在his blog post中解释的那样,使用std::future策略的std::async调用返回的launch::async的析构函数需要阻塞,直到生成的线程完成执行(§30.6.8[futures.async] / p5):

  

如果实施选择launch::async政策,

     
      
  • [...]
  •   
  • 关联的线程完成(1.10)同步   从成功检测到就绪的第一个函数返回   共享状态的状态或从最后一个函数返回的状态   释放共享状态,以先发生者为准。
  •   

在这种情况下,future的析构函数是“释放共享状态的最后一个函数”,因此线程完成必须同步(即,之前发生)返回那个功能。

答案 1 :(得分:0)

我查看了std :: future的文档,发现这是std :: future的析构函数:

释放任何共享状态。这意味着

  • 如果返回对象或提供者持有对其共享状态的最后一个引用,则共享状态被销毁;和
  • 返回对象或提供者放弃对其共享状态的引用;和
  • 这些操作不会阻止共享状态准备就绪,除非它可能会阻塞以下所有条件都成立:共享状态是通过调用std :: async创建的,共享状态是尚未准备好,这是对共享状态的最后一次引用。

注意最后一点。在我看来,你必须在范围的最后调用get