我是CPP的初学者,我们已经在类里面讨论了线程主题。
我正在尝试使用它,但它似乎无法按我的意愿工作。
我希望每个线程在 vector 中插入j的数量,然后将 vector 打印到控制台。
似乎所有这些对象都在循环结束后将j保留的最后一个值打印为“10”。

vector<int> foo(int x) {
    vector<int> a;
    a.push_back(x);
    return a;
}

void print(vector<int> vec) {
    for (int i = 0; i<int(vec.size()); i++)
        cout << vec[i] <<endl;
}

void foo2(int x) {
    vector<int> b;
    thread thr([&] {b = foo(x); });
    thr.join();
    mtx1.lock();
    print(b);
    mtx1.unlock();
}

int main() {
    vector<thread> th;
    for (int j = 0; j < 10; j++)
        th.emplace_back(([&] {foo2(j); }));
    for (int j = 0; j < 10; j++)
        th[j].join();
}
注意:我希望线程 vector 将进入函数内部,并调用一个新线程,该线程会将数字插入 vector ,然后进行打印。
我得到的输出是:
10
10
10
10
10
10
10
10
10
10
我的目标是:
0
1
2
3
4
5
6
7
8
9
谢谢你的帮助。

最佳答案

for (int j = 0; j < 10; j++)
    th.emplace_back(([&] {foo2(j); }));

lambda通过引用捕获j(毕竟[&]的意思是),lambda习惯于构造一个新的std::thread,并且此for循环立即迭代,递增j

但是,如果您一直密切注意,您会注意到j是通过引用捕获的,并且C++不提供任何保证,无论如何,新线程将在j循环之前读取foo2()的值并调用for。父线程迭代并增加j

这里发生的是,for循环运行得足够快,因此它可以在所有线程实际开始独立运行之前完成,并且它们所看到的只是j的最后一个值(甚至不行,因为此特定的j超出了范围)并在此for循环终止时被销毁,因为它被声明为for循环本地,从技术上讲,这意味着访问j makes demons fly out of your nose)。

解决方案:按值捕获j(可以是[=][j]),而不是引用。

P.S.即使执行了此操作,也无法保证从0到9的所有值都将按顺序打印。这完全取决于以特定顺序执行std::cout << ...的线程,同样,您绝对不能保证哪个线程将与所有其他线程相关地到达该语句。

关于c++ - 所有线程都做相同的事情。 cpp,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/62365600/

10-17 01:57