我正在努力理解C/C++中的线程联接。我知道
std::thread::join((函数使当前线程等待*this标识的线程完成执行。
但我不明白为什么联接函数的定位很重要,以及为什么这两个代码的工作方式不同。
代码1:
#include <iostream>
#include <thread>
#include<vector>
#include <unistd.h>
using namespace std;
void func(int x)
{
sleep(100);
cout<<x<<endl;
}
int main() {
vector<thread> a;
for(int i=0;i<10;i++)
{
a.emplace_back(func,i);
}
for (auto &thr : a) {
thr.join();
cout<<"next"<<endl;
}
cout<<"finish"<<endl;
}
输出:
01
3
next
9
7
45
6
8
2next
next
next
next
next
next
next
next
next
finish
代码2:
#include <iostream>
#include <thread>
#include<vector>
#include <unistd.h>
using namespace std;
void func(int x)
{
sleep(100);
cout<<x<<endl;
}
int main() {
vector<thread> a;
for(int i=0;i<10;i++)
{
a.emplace_back(func,i);
a.back().join();
cout<<"next"<<endl;
}
cout<<"finish"<<endl;
}
输出:
0
next
1
next
2
next
3
next
4
next
5
next
6
next
7
next
8
next
9
next
finish
起初,我认为在代码1中,当我稍后加入线程时,它们可能已经执行并完成了,但增加睡眠时间会得到相同的结果。所以,我很困惑。
在您的第一个版本的代码中,这个块
for(int i=0;i<10;i++)
{
a.emplace_back(func,i);
}
它做两件事,创建一个std::thread
实例并启动线程。现在,这些线程被允许运行,直到主线程在它们上调用join()
,就像在下一段代码中一样
for (auto &thr : a) {
thr.join();
cout<<"next"<<endl;
}
所以你,
- 创建所有线程
- 让他们都跑吧
- 逐一呼叫
join()
在版本2中,您再次创建线程,但随后立即通过back()
在最后插入的线程上调用join()
,即刚刚创建的线程。
for(int i=0;i<10;i++)
{
a.emplace_back(func,i);
a.back().join();
cout<<"next"<<endl;
}
因此,每个线程都被启动、运行到完成,然后被称为join()
。您本质上是序列化线程,从而生成输出。给你,
- 创建单个线程
- 允许它运行
- 呼叫
join()
- 对所有螺纹重复此操作
在第一个代码段中,启动所有线程,然后等待所有线程。在第二个片段中,您等待线程在启动后立即完成,然后再转到下一个线程,因此一次只运行一个线程。