繁体   English   中英

为什么调用从异步检索的 future.get() 会导致意外的 output 订单

[英]Why calling future.get() retrieved from async leads to unexpected output order

考虑以下代码:

#include <iostream>
#include <vector>
#include <thread>
#include <mutex>
#include <future>

std::mutex mutex;

int generate()
{
    static int id = 0;
    std::lock_guard<std::mutex> lock(mutex);
    id++;
    std::cout << id << '\n';
    return id;
}

int main()
{
    std::vector<std::future<int>> vec;
    std::vector<int> result;
    for(int i = 0; i < 10; ++i)
    {
        vec.push_back(std::async(std::launch::async,generate));
    }
    for(int i = 0; i < 10; ++i)
    {
        result.push_back(vec[i].get());
    }
    std::cout << "\n result:";
    for(const auto res : result)
    {
        std::cout << res << " ";
    }
}

产生以下 output:

1
2
3
4
5
6
7
8
9
10

 result:1 2 3 6 4 5 7 8 9 10

如您所见, generate() function 中的 output 具有正确的(从 1 到 10)顺序。 但是当迭代结果向量时,每次运行我都会得到不同的顺序。 为什么会发生这种情况,如何同步此类代码?

您在最终 output 中看到的是线程产生结果的顺序。

将这三个线程视为简化版本:

          +- -+   +- -+    +- -+
Thread    | 1 |   | 2 |    | 3 |
          +- -+   +- -+    +- -+
Result    |   |   |   |    |   |
          +- -+   +- -+    +- -+

现在,无论这些执行哪个命令并获取互斥锁,output 将是

1 2 3

因为idstatic ,第一个“储物柜”将其递增并打印“1”,然后第二个将其递增并打印“2”,依此类推。

让我们假设线程 3 首先获得互斥锁,然后是 1,然后是 2。

这导致了这种情况:

          +- -+   +- -+    +- -+
Thread    | 1 |   | 2 |    | 3 |
          +- -+   +- -+    +- -+
Result    | 2 |   | 3 |    | 1 |
          +- -+   +- -+    +- -+

当您以“矢量顺序”打印结果时,您会看到

2 3 1

如果您希望线程以某种预定顺序执行,则需要进一步同步它们。

如果您立即解决未来,那么它将是按顺序排列的。 例如:

#include <iostream>
#include <vector>
#include <thread>
#include <mutex>
#include <future>

std::mutex mutex;

int generate()
{
    static int id = 0;
    std::lock_guard<std::mutex> lock(mutex);
    id++;
    std::cout << id << '\n';
    return id;
}

int main()
{
    std::vector<std::future<int>> vec;
    std::vector<int> result;
    for(int i = 0; i < 10; ++i)
    {
        int result = std::async(std::launch::async,generate).get();
        result.push_back(result);
    }
    std::cout << "\n result:";
    for(const auto res : result)
    {
        std::cout << res << " ";
    }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM