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

时间:2016-05-15 06:13:59

标签: c++ multithreading c++11 asynchronous

我正在运行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;
}

我最初的期望是看到&#34; MAIN THREAD&#34; printout出现之前&#34; foo()线程清醒&#34;因为这两个线程是异步运行的,foo()由于其休眠行为而落后。然而,这不是实际发生的事情。对res.get()的调用会阻塞,直到foo()被唤醒,然后才会进入&#34; MAIN THREAD&#34;打印。这表示同步行为,所以我想知道如果我或许要么缺少某些东西,要么不完全掌握实现。我已经看了很多关于此事的帖子,但仍然无法理解它。任何帮助将不胜感激!

3 个答案:

答案 0 :(得分:6)

 res.get();

阻塞,直到异步完成。

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

无论您如何判断它的运行情况,get都无法为您提供结果,直到完成为止。

答案 1 :(得分:1)

嗯,这就是std::future::get的工作方式 - 它会阻止future提供某些结果或例外。

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

我的想法是异步启动一些任务,同时执行某些操作,只在需要结果时调用get,正如您可能想到的那样,它不是最具扩展性的东西..

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

#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

答案 2 :(得分:0)

问题是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;
}