C++11 线程与异步



考虑以下两个代码片段,我正在尝试启动 10000 个线程:

片段 1

    std::array<std::future<void>, 10000> furArr_;
    try
    {
        size_t index = 0;
        for (auto & fut : furArr_)
        {
            std::cout << "Created thread # " << index++ << std::endl;
            fut = std::async(std::launch::async, fun);
        }
    }
    catch (std::system_error & ex)
    {
        std::string str = ex.what();
        std::cout << "Caught : " << str.c_str() << std::endl;
    }
    // I will call get afterwards, still 10000 threads should be active by now assuming "fun" is time consuming

片段 2

    std::array<std::thread, 10000> threadArr;
    try
    {
        size_t index = 0;
        for (auto & thr : threadArr)
        {
            std::cout << "Created thread # " << index++ << std::endl;
            thr = std::thread(fun);
        }
    }
    catch (std::system_error & ex)
    {
        std::string str = ex.what();
        std::cout << "Caught : " << str.c_str() << std::endl;
    }

第一种情况总是成功的,即我能够创建 10000 个线程,然后我必须等待所有线程完成。在第二种情况下,几乎总是在创建 1600+ 线程后最终出现异常("资源不可用重试"(。

使用std::launch::async的启动策略,我认为这两个代码段的行为方式应该相同。具有异步启动策略的 std::async 与使用 std::thread 显式启动线程有何不同?

我在Windows 10,VS2015上,二进制是在x86发布模式下构建的。

首先,感谢Igor Tandetnik为我提供了这个答案的方向。

当我们使用 std::async(带有异步启动策略(时,我们说:

"我想在单独的线程上完成这项工作"。

当我们使用std::thread时,我们说:

"我想在新线程上完成这项工作"。

细微的区别意味着async(通常(使用线程池实现。这意味着如果我们多次使用 async 调用一个方法,通常该方法中的线程 id 会重复,即 async将多个作业分配给池中的同一组线程。而对于std::thread,它永远不会。

这种差异意味着显式启动线程可能比将asyncasync启动策略一起使用更占用资源(因此例外(。

最新更新