std::launch::async就像同步进程一样阻塞



我正在运行Visual Studio 2012,并试图了解std::async的工作原理。我创建了一个非常简单的C++控制台应用程序:

#include "stdafx.h"
#include <future>
#include <iostream>
void foo() {
    std::cout << "foo() thread sleep" << std::endl;
    std::this_thread::sleep_for(std::chrono::seconds(5));
    std::cout << "foo() thread awake" << std::endl;
}
int main()
{
    std::future<void> res = std::async(std::launch::async, foo);
    res.get();
    std::cout << "MAIN THREAD" << std::endl;
    system("pause");
    return 0;
}

我最初的期望是看到"MAIN THREAD"打印输出在"foo()THREAD wake"之前出现,因为这两个线程是异步运行的,而foo(()由于其睡眠行为而落后。然而,事实并非如此。对res.get()的调用会阻塞,直到foo()唤醒,然后才到达"MAIN THREAD"打印输出。这表示同步行为,所以我想知道,如果我遗漏了什么,或者没有完全掌握实现,会怎么样。我已经看了很多关于这件事的帖子,但仍然无法理解。任何帮助都将不胜感激!

 res.get();

块,直到异步完成。

http://en.cppreference.com/w/cpp/thread/future/get

不管你如何告诉它运行,get在完成之前都不能给你结果。

好吧,这就是std::future::get的工作方式——它会阻塞,直到future有一些结果或异常要提供。

这并不意味着async是同步工作的,它是异步工作的,这只是因为您阻塞了等待结果的线程。

这个想法是异步启动一些任务,同时做一些事情,只在需要结果时调用get,正如你可能会发现的那样,这不是最具可扩展性的事情。。

如果使用Visual Studio 2015,则可以访问std::futureconcurrency::task(Microsoft PPL库)以及您自己的兼容定义类型的await关键字。这实现了无阻塞行为。

#include "stdafx.h"
#include <future>
#include <iostream>
void foo() {
    std::cout << "foo() thread sleep" << std::endl;
    std::this_thread::sleep_for(std::chrono::seconds(5));
    std::cout << "foo() thread awake" << std::endl;
}
std::future<void> entry(){
     await std::async(std::launch::async, foo);
     std::cout << "foo has finished, back in entry()n";
}
int main()
{
    std::cout << "MAIN THREAD" << std::endl;
    entry();
     std::cout << "BACK INMAIN THREAD" << std::endl;
    system("pause");
    return 0;
} //make sure to compile with /await flag

问题是res.get()必须等待其线程完成才能获得结果(如果有的话)。要查看运行中的并发性,需要将get()移到要同时运行的其他代码之后。

这个例子可能会让它变得更清晰:

#include <ctime>
#include <cstdlib>
#include <future>
#include <iostream>
void foo(int id) {
    std::cout << "foo(" << id << ") thread sleep" << std::endl;
    // random sleep
    std::this_thread::sleep_for(std::chrono::seconds(std::rand() % 10));
    std::cout << "foo(" << id << ") thread awake" << std::endl;
}
int main()
{
    std::srand(std::time(0));
    std::future<void> res1 = std::async(std::launch::async, foo, 1);
    std::future<void> res2 = std::async(std::launch::async, foo, 2);
    std::future<void> res3 = std::async(std::launch::async, foo, 3);
    std::cout << "MAIN THREAD SLEEPING" << std::endl;
    std::this_thread::sleep_for(std::chrono::seconds(20));
    std::cout << "MAIN THREAD AWAKE" << std::endl;
    // now wait for all the threads to end
    res1.get();
    res2.get();
    res3.get();
    system("pause");
    return 0;
}

最新更新