thread.join()在多线程中做什么



我正在努力理解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;
}

所以你,

  1. 创建所有线程
  2. 让他们都跑吧
  3. 逐一呼叫join()

在版本2中,您再次创建线程,但随后立即通过back()在最后插入的线程上调用join(),即刚刚创建的线程。

for(int i=0;i<10;i++)
{
a.emplace_back(func,i);
a.back().join();
cout<<"next"<<endl;
}

因此,每个线程都被启动、运行到完成,然后被称为join()。您本质上是序列化线程,从而生成输出。给你,

  1. 创建单个线程
  2. 允许它运行
  3. 呼叫join()
  4. 对所有螺纹重复此操作

在第一个代码段中,启动所有线程,然后等待所有线程。在第二个片段中,您等待线程在启动后立即完成,然后再转到下一个线程,因此一次只运行一个线程。

最新更新