C ++程序意外阻止/抛出

时间:2014-10-09 12:46:07

标签: c++ multithreading c++11

我正在学习C ++中的互斥体,并且遇到以下代码的问题(摘自N. Josuttis的“C ++标准库”)。

我不明白为什么它阻止/抛出除非我在主线程中添加 this_thread::sleep_for(然后它不会阻塞并执行所有三个调用)。

编译器是从命令行使用的cl.exe。

#include <future>
#include <mutex>
#include <iostream>
#include <string>
#include <thread>
#include <chrono>

std::mutex printMutex;

void print(const std::string& s)
{
    std::lock_guard<std::mutex> lg(printMutex);

    for (char c : s)
    {
        std::cout.put(c);
    }
    std::cout << std::endl;
}

int main()
{
    auto f1 = std::async(std::launch::async, print, "Hello from thread 1");
    auto f2 = std::async(std::launch::async, print, "Hello from thread 2");

    // std::this_thread::sleep_for(std::chrono::seconds(1));

    print(std::string("Hello from main"));       
}

3 个答案:

答案 0 :(得分:11)

我认为您所看到的是async的MSVC实施(与future结合)的一致性问题。我相信它是not conformant。我可以用VS2013重现它,但无法用gcc重现这个问题。

崩溃是因为主线程在其他两个线程完成之前退出(并开始清理)。

因此,两个期货的简单延迟(sleep_for)或.get().wait()应该为您解决。因此修改后的main可能看起来像;

int main()
{
    auto f1 = std::async(std::launch::async, print, "Hello from thread 1");
    auto f2 = std::async(std::launch::async, print, "Hello from thread 2");

    print(std::string("Hello from main"));       

    f1.get();
    f2.get();
}

支持明确等待或克服定时“睡眠”。

有关一致性的说明

来自Herb Sutter的提案更改了从future返回的async的共享状态的等待或阻止。这可能是MSVC行为的原因,可以看作已实施该提案。我不确定该提案的最终结果是什么,或者它与C ++ 14的集成(或其中的一部分)。至少w.r.t.阻止从future返回的async,看起来MSVC行为没有进入规范。

值得注意的是,§30.6.8/ 5中的措辞有所改变;

来自C ++ 11

  

对共享创建的共享状态的异步返回对象的等待函数的调用   通过此async调用将阻塞,直到关联的线程完成,就像加入

一样

To C ++ 14

  

对共享创建的共享状态的异步返回对象的等待函数的调用   通过此async调用将阻塞,直到关联的线程完成,就好像已加入,或其他时间   退出

我不确定如何指定“超时”,我认为它是实现定义的。

答案 1 :(得分:1)

std::async会返回future。如果getwait未被调用,则会destructor阻止:

  

如果满足以下所有条件,它可能会阻塞:共享状态是通过调用std :: async创建的,共享状态尚未就绪,这是对共享状态的最后一次引用。

有关该主题的详细处理,请参阅std::futures from std::async aren't special!

答案 2 :(得分:1)

main

的末尾添加这两行
f1.wait();
f2.wait();

这将确保线程在main存在之前完成。