std :: async函数串行运行

时间:2016-10-10 11:55:37

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

在for循环中使用std :: async和launch :: async时,我的代码在同一个线程中串行运行,就好像每个异步调用在启动之前等待前一个异步调用一样。在std :: async引用(std::async)的注释中,如果std :: future未绑定到引用,则可以这样做,但我的代码不是这种情况。任何人都可以找出它为什么连续运行?

这是我的代码段:

class __DownloadItem__ { //DownloadItem is just a "typedef shared_ptr<__DownloadItem__> DownloadItem"
    std::string buffer;
    time_t last_access;
 std::shared_future<std::string> future;
}

for(uint64_t start: chunksToDownload){
        DownloadItem cache = std::make_shared<__DownloadItem__>();
        cache->last_access = time(NULL);
        cache->future =
                std::async(std::launch::async, &FileIO::download, this, api,cache, cacheName, start, start + BLOCK_DOWNLOAD_SIZE - 1);
     }
}

未来将存储在共享的未来,因为多个线程可能正在等待同一个未来。

我也在使用GCC 6.2.1进行编译。

3 个答案:

答案 0 :(得分:5)

析构函数中std::future块返回的async。这意味着当您到达}

for(uint64_t start: chunksToDownload){
    DownloadItem cache = std::make_shared<__DownloadItem__>();
    cache->last_access = time(NULL);
    cache->future =
            std::async(std::launch::async, &FileIO::download, this, api,cache, cacheName, start, start + BLOCK_DOWNLOAD_SIZE - 1);
 }  // <-- When we get here

cache被销毁,后者又调用future的析构函数来等待线程完成。

您需要做的是将future返回的每个async存储在for循环之外声明的单独的持久future中。

答案 1 :(得分:1)

这是C ++ 11定义的std::async的错误。它的未来&#39;析构函数是特殊的,等待操作完成。有关Scott's Meyers博客的详细信息。

cache在每次循环迭代结束时被销毁,从而调用其子对象的析构函数。

使用packaged_task或确保为您的cache保留一个共享指针副本的容器,以避免等待析构函数。就个人而言,我会选择packeged_task

答案 2 :(得分:0)

正如您所注意到的那样,future future std::async的{​​{1}} d-tor阻止等待异步操作完成(future成为ready {1}})。 在您的情况下,cache对象在每个循环迭代中超出范围,因此被破坏,并且与它所拥有的future一起被破坏,因此您可以看到上述效果。