为什么std::async即使指定了std::launch::async标志,也要同步调用函数?

Why does std::async call the function synchronously even with the specified std::launch::async flag

本文关键字:std async 同步 函数 调用 launch 为什么 标志      更新时间:2023-10-16

我传递给std::async的函数打印当前线程id。尽管使用std::launch::async标志调用,它打印相同的头id。这意味着它同步调用函数。为什么?

void PrintThreadId()
{
    std::cout << std::this_thread::get_id() << std::endl;
}
int main()
{
    for (int i = 0; i < 5; ++i)
    {
        auto f = std::async(std::launch::async, PrintThreadId);
        f.wait();
    }
}

输出如下:2093620936209362093620936

环境:VS 2015, W7.

提前感谢!

实际上通过等待每个调用来序列化调用,因此可以重用相同的线程,而不会破坏std::future由与调用线程

不同的线程执行的规范。

当以下代码显示与其他代码相同的Caller ThreadId时唤醒我们:

void PrintThreadId()
{
    std::cout << std::this_thread::get_id() << std::endl;
}
int main()
{
    std::cout << "Caller threadId (to be different from any id of the future exec thread): ";
    PrintThreadId();
    for (int i = 0; i < 5; ++i)
    {
        auto f = std::async(std::launch::async, PrintThreadId);
        f.wait();
    }
}

你的future生命周期结束于函数每次迭代的作用域。与它关联的线程也会死亡。实现以后可以自由地重用它,即在循环的下一次迭代中。

如果您修改示例代码以打印当前线程id,您将看到当前线程是不同的:

for (int i = 0; i < 5; ++i)
{
    PrintThreadId();
    auto f = std::async(std::launch::async, PrintThreadId);
    f.wait();
}

现场演示

您还应该考虑返回async的期货是特殊的-在析构函数中它们会阻塞直到任务未完成。更多关于Scott Meyers博客的信息,在相反的标题下: std::futures来自std::async并不特殊