简单理解c++的thread.join()

首先说结论

你其实可以将它简单的理解为等待指定的线程完成工作后再进行下一步

首先我们知道thread对象的创建它只管创建,创建之后子线程干了啥他不管,但是有些任务当中我们需要多个线程完成任务之后才能继续,这时候就可以使用join函数了

那么我们来证明一下上面说的结论

简单写了个例子

thread的默认构造中第一个参数为函数名,后面的位置为函数的参数,参数的数量没有限制,最开始我学多线程就懵在这里了

#include <iostream>
#include <thread>
using namespace std;

void out(int a) {
	cout << a << endl;
	if (a >= 20)
	{
		return;
	}
	thread t(out, ++a);
	t.join();
	cout << a << endl;
}

int main() {

	thread t(out, 10);
	t.join();
	cout << "主线程解锁" << endl;

	return 0;
}

在看结果之前请先预测一下结果

*

*

*

*

下面是结果

10
11
12
13
14
15
16
17
18
19
20
20
19
18
17
16
15
14
13
12
11
主线程解锁

先说一下上面的案例干了什么

在以上的测试案例当中我们在主线程里创建了一个子线程,同时子线程内部又创建了它的子线程,在每次创建时对子线程传递参数并加1,直到a的值大于>=20的时候结束。

那么我们来说结果

首先我们把结果分成三部分分别是:第一部分 10-20、第二部分 20-11、第三部分 主线程解锁。

为了方便描述,以下用方法内用a的初始值也就是刚传入的时候的值来称呼

分别分析每一部分是怎么来的,先忽略主方法内的join,只把他当成普通的调用out函数。第一部分是out函数的第一行输出传入的参数a,因为最开始的out是被主方法调用的并且传入了10所以第一个输出的数为10。紧接着看第二行是判断a的大小,此时a显然小于20那么直接看第六行。第六行是调用自身并且传入的值为a+1,但是因为创建的是thread对象,所以函数应继续向下执行而不应该在此停留但同时又多出了一个线程,这个新的线程应从out函数的第一句开始重新执行。现在我们回到刚才讨论的线程,他的第七行是t.join()也就是等待t对象执行结束才返回该函数,也就是说他的子线程在结束之前调用join函数的线程不会再向下执行了,这也就意味着他的第八行输出a暂时不能执行。

现在我们来看out函数调用自身并创的子线程也就是我们的第三个线程,他也要走一遍我们上面的分析,唯一的不同在于他的a的值为11,此时他又会创建他的子线程也就是第四个子线程此时a=12,如此直到a=20的时候达成了if语句的条件,此时return语句触发结束了结束了a=20的函数。此时a=19的函数内的join发现他的t函数返回了,那么a=19这个函数可以继续执行了,那么它的第八行代码可以被执行了,也就是输出第二部分的 20-11 的部分,此时第九句执行,a=19的函数被返回a=18的函数可以继续执行,以此直到所有函数均结束。

都结束后主线程发现他的t函数也结束了此时主函数也可以继续执行,也就是我们结果的第三部分“主线程解锁”。

因为创建子线程传递参数时使用的是++a所以a的值增加了也就是第二部分的值全部+1

至此我们简单分析了join函数的使用

但是,还有一个疑问没有解决,如果调换一下顺序会怎样直接上代码不做分析了

#include <iostream>
#include <thread>
using namespace std;

void out(int a) {
	cout << a << endl;
	if (a >= 20)
	{
		return;
	}
	thread t(out, ++a);
	cout << a << endl;
	t.join();
}

int main() {

	thread t(out, 10);
	cout << "主线程解锁" << endl;
	t.join();

	return 0;
}

以下是结果

主线程解锁
10
1111

12
12
1313

14
14
15
15
16
16
17
17
18
18
1919

2020

可以看到,各线程分开工作没有互不冲突了,此时我们再稍微修改一下以此印证我们的结论

#include <iostream>
#include <thread>
using namespace std;

void out(int a) {
	cout << a << endl;
	if (a >= 20)
	{
		return;
	}
	thread t(out, ++a);
	cout << a << endl;
	t.join();
	cout << a << endl;
}

int main() {

	thread t(out, 10);
	cout << "主线程解锁" << endl;
	t.join();

	return 0;
}
主线程解锁
10
1111

1212

1313

14
14
15
15
1616

1717

1818

1919

2020

20
19
18
17
16
15
14
13
12
11

可见最后输出的20-11也就是join函数造成的结果

以上就是本篇文章的全部内容,分析那段可能写的比较臃肿,见谅

如果还有什么问题或者有些建议的话可以写在评论

  • 9
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值