并发与多线程笔记2

一:范例 线程运行的开始和结束

1.1 先写一个最简单的程序:

#include <iostream>//输入输出头文件

// 程序运行起来,生成一个进程,该进程所属的主线程自动运行。
int main()
{
	std::cout << "I LOVE CHINA!" << std::endl;//实际上这个是主线程执行。
	return 0;
}

非常简单,就是开启了一个进程,主线程从main函数开始执行,最后主线程结束退出

1.2 自己创建线程(子线程)方法:

  1. 包含头文件thread;
  2. 创建一个函数入口;
  3. 写代码。
	// 主线程从main函数开始执行,那我们自己创建的线程,
	//也需要从一个函数开始运行(初始函数),
	//一旦此函数运行完毕, 就代表此线程运行结束
#include <iostream>//输入输出头文件
#include <thread>//包含线程头文件

using namespace std;

// 自己创建的线程也要从一个函数运行(函数入口)
void myprint()
{
   cout << "我的线程开始了。。。。。" << endl;

   cout << "我的线程结束了。。。。" << endl;
}

int main()
{
	//创建子线程的具体代码
	//thread 是标准库里的类
	thread myobj(myprint);// myprint可调用对象。创建了线程,线程起点myprint,并开始执行。
	//阻塞主线程,让主线程等待子线程执行完毕,
	//然后子线程和主线程汇合,然后主线程继续。
	myobj.join();	//  主线程等待子线程(myprint)执行完毕,两者汇合后继续。

	//detach():传统多线程程序要主线程等到子线程完毕,然后主线程结束。
	//myobj.detach();//这条语句的效果可以多运行几次看结果差异。

	cout << "我是主线程,我要安全退出了!" << endl;
	return 0;
}

运行结果如下:
在这里插入图片描述
如果用 d e t a c h ( ) detach() detach()的话:
在这里插入图片描述
这说明 d e t a c h ( ) detach() detach()并没有要求主线程等待子线程执行完再退出

detach: 主线程不与子线程汇合,各自走各自的路,不必等子线程运行结束了。
为啥要引入这种机制?如果子线程太多,主线程非得等每个都执行完,也不是很好。(建议不要用detach)
一旦detach之后,与主线程关联的thread对象就会失去与主线程关联,此时子线程就会驻留在系统后台运行。
子线程就相当于被c++运行时库接管,当子线程执行完毕时,由运行时库负责清理该线程的相关资源(守护线程)。
detach使子线程失去了控制,一旦detach了就无法再join回来了。


再来介绍一下 j o i n a b l e ( ) joinable() joinable(),他是为了判断是否可以成功使用join()或detach()

if (myobj.joinable())//返回true或false
{
	cout << "joinable == true.\n" << endl;//如果前面没join过
	myobj.join();
}

二、其他创建线程的方法

2.1 用类可调用对象

#include <iostream>//输入输出头文件
#include <thread>//包含线程头文件

using namespace std;

//用类创建入口
class TA
{
public:
	void operator()()//重载括号运算符,可调用函数
	{
		cout << "我的线程operator()开始了。。。。。" << endl;

		cout << "我的线程operator()结束了。。。。。" << endl;
	}
};

int main()
{
	//创建子线程的具体代码
	TA ta;//创建一个类对象
	//thread 是标准库里的类
	thread myobj1(ta);// ta可调用对象。创建了线程,线程起点重载函数(),并开始执行。
	//阻塞主线程,让主线程等待子线程执行完毕,
	//然后子线程和主线程汇合,然后主线程继续。
	myobj1.join();	//  主线程等待子线程重载函数()执行完毕,两者汇合后继续。

	//detach():传统多线程程序要主线程等到子线程完毕,然后主线程结束。
	//myobj.detach();//这条语句的效果可以多运行几次看结果差异。

	cout << "我是主线程,我要安全退出了!" << endl;
	return 0;
}

运行结果如下:
在这里插入图片描述
上面有一个问题,如果调用了detach,主线程结束后这个ta还在吗?(不在了)那子线程怎么运行呢?(这个对象实际上是被复制到子线程去,复制的依旧存在
怎么证明这个对象是被复制进去的呢
我们可以打印出 t a ta ta 在主线程和子线程中分别的地址验证。
在我的机器上:
在这里插入图片描述
可以看出两者地址不一样,子线程中的对象是复制的存在。

2.2 用lamada表达式

auto mylamdathread = [] {
	cout << "线程3开始执行了!" << endl;

	cout << "线程3结束执行了!" << endl;
};

thread mytobj4(mylamdathread);
mytobj4.join();

运行结果如下:
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

宛如新生

转发即鼓励,打赏价更高!哈哈。

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值