
我想用 thread 并发处理 for 循环,但总是 join 放在循环外就会出错,是 lambda 的问题吗?
vector<thread> threads; for (int k = 1; k < d; k++) { thread t1([&](){ A_result[k] = Linear_Transform_Plain(A_result[0], params); }); thread t2([&](){ B_result[k] = Linear_Transform_Plain(B_result[0], params); }); threads.push_back(t1); threads.push_back(t2); // join 在里面就不会出错 // t1.join(); // t2.join(); } for(auto i = threads.begin(); i != threads.end(); i++){ i->join(); } 报错:
terminate called after throwing an instance of 'std::bad_alloc' what(): std::bad_alloc Aborted (core dumped) 尝试过换用thread threads[14]然后索引赋值的方法,报错:
terminate called recursively Aborted (core dumped) 然后不用 lambda 就可以运行,但获取不到返回值了
thread threads[14]; for (int k = 1; k < d; k++) { threads[k-1] = thread(Linear_Transform_Plain, A_result[0], params); threads[k-1+7] = thread(Linear_Transform_Plain, B_result[0], params); } for (int k = 1; k < d; k++) { threads[k-1].join(); threads[k-1+7].join(); } 网上找了大多是基础用法和线程池,并不能达到我想要的全核心并发处理。
这里先感谢各位了!
1 hankai17 2020-07-15 20:47:45 +08:00 thread 不支持 copy? |
3 gantleman 2020-07-15 21:07:49 +08:00 从 C++的语法来说你在 for 循环里声明了两个 thread t1 t2 的局部变量。 离开 for 循环后这两个局部变量被销毁,任何使用的操作都是非法的。建议你改用 new 尝试下。 |
4 nightwitch 2020-07-15 21:08:11 +08:00 第一个里面,不要用引用去捕获 k 的值,k 的值一直在变,而且当 for 循环结束以后,k 的生命周期结束,你的 lambda 里面的 k 就是空悬引用。 |
5 nightwitch 2020-07-15 21:11:22 +08:00 @gantleman t1,t2 被 push 到 vector 里面去了啊 |
6 nannanziyu 2020-07-15 21:17:32 +08:00 std::thread 没有拷贝构造函数 http://www.cplusplus.com/reference/thread/thread/thread/ 3) copy constructor Deleted constructor form (thread objects cannot be copied). 所以修改 threads.push_back(t1); 为 threads.push_back(std::move(t1)) |
7 V2WT 2020-07-15 21:20:44 +08:00 ``` #include <iostream> #include <thread> #include <vector> #include <algorithm> int main() { // vector container stores threads std::vector<std::thread> workers; for (int i = 0; i < 5; i++) { workers.push_back(std::thread([]() { std::cout << "thread function\n"; })); } std::cout << "main thread\n"; // Looping every thread via for_each // The 3rd argument assigns a task // It tells the compiler we're using lambda ([]) // The lambda function takes its argument as a reference to a thread, t // Then, joins one by one, and this works like barrier std::for_each(workers.begin(), workers.end(), [](std::thread &t) { t.join(); }); return 0; } ``` I found these code, from here: [click]( https://www.bogotobogo.com/cplusplus/C11/3_C11_Threading_Lambda_Functions.php). Hope this would help! |
8 nannanziyu 2020-07-15 21:23:14 +08:00 然后还有 4 楼说的,你的 k 不能传引用,要传值 改成 std::thread t1([&,k]() { }); |
9 Huelse OP @nannanziyu #6 @nightwitch #4 感谢感谢~ 综合两位的答案,将第一个例子改成 ``` std::thread t1([&, k](){ A_result[k] = ... }); threads.push_back(std::move(t1)); ``` 就可以了,核心跑满,舒服了~ |
10 gantleman 2020-07-15 21:27:12 +08:00 @nightwitch 是的,6 楼是正确答案 |
11 GeruzoniAnsasu 2020-07-15 21:29:04 +08:00 c++11 以后不要记得容器有 push_back 这个函数 一律用 emplace_back,这个函数会自动转发左右值引用 emplace_back 还有一个重载是用入参构造元素,所以可以 threads.emplace_back([&](){WHATEVER}) |
12 billyzs 2020-07-16 01:34:49 +08:00 @GeruzoniAnsasu 这个例子直接上 emplace_back()没问题,不过明确需要拷贝左值的时候 push_back()可读性更高 [https://abseil.io/tips/112]( https://abseil.io/tips/112) |
13 tusj 2020-07-16 09:50:16 +08:00 threads.push_back(std::move(t1)); |
14 Sentan 2020-07-16 09:54:34 +08:00 @nannanziyu 大佬,问下,用 std:move 处理 tread 那个对象,把他变成左值是为了什么,这样是会把这个对象的生命周期变长吗,还是说让他从栈空间变成堆空间了? |
15 Wirbelwind 2020-07-16 10:37:18 +08:00 @Sentan thread 只有移动语义,所以不能 copy,只能转让所有权,用 std::move 告诉编译器调用移动构造 |
16 Wirbelwind 2020-07-16 10:37:48 +08:00 |
17 Sentan 2020-07-16 15:03:31 +08:00 @Wirbelwind 哦哦,明白了 |
18 hardwork 2020-08-13 20:42:52 +08:00 你这个和 std::async + future 用法有点像的 |