我有以下非常简单的代码:
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
。
答案 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()
,那么它应该是异步的。