std :: async不会异步工作

时间:2017-06-20 13:33:23

标签: c++ c++11 asynchronous

我有以下非常简单的代码:

void TestSleep()
{
    std::cout << "TestSleep " << std::endl;
    sleep(10);
    std::cout << "TestSleep Ok" << std::endl;

}

void TestAsync()
{
    std::cout << "TestAsync" << std::endl;
    std::async(std::launch::async, TestSleep);
    std::cout << "TestAsync ok!!!" << std::endl;

}

int main()
{
    TestAsync();
    return 0;
}

由于我使用std::launch::async,我希望TestSleep()将异步运行,我将得到以下输出:

TestAsync
TestAsync ok!!!
TestSleep 
TestSleep Ok

但实际上我有同步运行的输出:

TestAsync
TestSleep 
TestSleep Ok
TestAsync ok!!!

你能解释为什么以及如何真正地异步调用TestSleep

2 个答案:

答案 0 :(得分:7)

来自this std::async reference notes section

  

如果从std::future获取的std::async未从引用移动或绑定到引用,则std::future的析构函数将在完整表达式结束时阻塞,直到异步操作完成,基本上使代码...同步

这就是这里发生的事情。由于你没有存储std::async返回的未来,它将在表达式的末尾(这是std::async调用)被破坏,并且将一直阻塞直到线程结束。

如果你这样做。

auto f = std::async(...);

然后f末尾的TestAsync的破坏将被阻止,文字"TestAsync ok!!!"应该在"TestSleep Ok"之前打印。

答案 1 :(得分:6)

std::async()返回std::future的实例。如果您查看std::future's destructor的文档,则会说明以下内容:

  

这些操作不会阻止共享状态变为就绪,除非它可能阻塞以下所有条件都是真的:共享状态是通过调用std :: async创建的,共享状态尚未准备好,这是对共享状态的最后一次引用。

您没有将std::async()的返回值存储到局部变量中,但该值仍然是已创建的,必须予以销毁。由于析构函数将阻塞直到函数返回,这使它同步。

如果您更改TestAsync()以返回由std::future()创建的std::async(),那么它应该是异步的。