我想用 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 1
第一个里面,不要用引用去捕获 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 1
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 1
然后还有 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 2
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 1
|
17
Sentan 2020-07-16 15:03:31 +08:00
@Wirbelwind 哦哦,明白了
|
18
hardwork 2020-08-13 20:42:52 +08:00
你这个和 std::async + future 用法有点像的
|