博客
关于我
C++并发与多线程(一)
阅读量:338 次
发布时间:2019-03-04

本文共 16951 字,大约阅读时间需要 56 分钟。

C++并发与多线程一

第一节 并发基本概念及实现, 进程 线程基本概念

一 并发线程 进程的基本概念和综述

1.1 并发:

两个或者更多的任务(独立的活动)同时发生:一个程序同时执行多个独立任务。
单核cpu,某一时刻只能执行一个任务,由操作系统调度,每秒钟进行多次所谓的“任务切换”。
假象(不是真正的并发))这种切换(上下文切换)是要有时间开销的。

1.2 可执行程序

例如windows下的exe文件

1.3 进程

一个可执行程序运行以后即创建了一个进程。
运行起来的可执行文件叫做一个进程。

1.4 线程

每个进程都有一个主线程,主线程唯一。
进程存在,主线程自动存在,所以一个进程中至少含有一个主线程。
运行程序时,实际是进程的主线程来运行。共存关系。
线程:执行代码,理解成一条代码的执行路径。
除主线程外,可以通过自己写代码来创建其他线程。
在这里插入图片描述
每创建一个新线程,可以在同一时刻做不同的事
多线程:线程并不是越多越好,每个线程都需要一个独立的堆栈空间,线程的切换要保存很多中间状态,会耗费本该属于程序运行的时间。
线程的优点:速度快,轻量级,系统资源开销更少,执行速度更快,通信快。
缺点:有难度,要小心处理数据一致性问题。

二 .并发的实现方法

(1)实现方法一:多进程实现并发

进程间的通讯:管道 文件 消息队列 共享内存
不同电脑通信:socket

(2)多线程并发

在单独的进程中,创建多个线程实现并发。
每个线程有自己独立的路径,一个进程中的所有线程共享地址内存,带来了数据一致性问题。
全局变量,指针,引用都可以在线程之间传递。
多线程开销远小于多进程。
优先考虑多线程,只谈多线程并发。

三 .C++新标准线程

以往的多线程代码不可跨平台:
window:CreateThread(), _beginthread() ,beginthread()创建线程
Linux:pthread_create() 创建线程。

POSIX thread(pthread) 可以实现跨平台,但配置繁琐。
C++11新标准增加对多线程的支持,可移植(跨平台)

第二节 线程启动、结束,创建线程、join,detach

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

1.1 thread类

thread myobj(myprint);			  //myprint 为可调用对象         此代码(1)创建线程,线程入口 myprint函数(2)myprint线程开始执行

1.2 join()函数

join函数阻塞主线程,让主线程等待子线程执行完毕,然后子线程和主线程汇合,再继续走主线程。

myobj.join();					 //join阻塞主线程,让主线程等待子线程执行完毕,然后子线程和主线程汇合,再继续走主线程		//如果不阻塞 主线程会早于子线程完成,子线程被强制终止 	//良好的程序应该主线程等待子线程完毕后才退出

下面这张图描述了主线程与子线程的通道状态,main和myprint在两个不同的线路中,如果main结束,则myprint一般情况下会被强行终止,但也有例外,下面的detach函数可以让主线程早于子线程结束。
主线程与子线程

1.3 detach()函数

传统多线程程序主线程要等待子线程再结束 ,detach函数使主线程不等待子线程运行,可以早于子线程结束,各自执行各自的程序。

#include "pch.h"#include <iostream>#include <thread>using namespace std;void myprint(){   	cout << "我的线程开始了" << endl;	cout << "我的线程结束了1" << endl;	cout << "我的线程结束了2" << endl;	cout << "我的线程结束了3" << endl;	cout << "我的线程结束了4" << endl;	cout << "我的线程结束了5" << endl;	cout << "我的线程结束了6" << endl;	cout << "我的线程结束了7" << endl;}int main(){   	cout << " i love china !" << endl;	//个主线程在执行,主线程从main函数返回,整个进程执行完毕	//主线程从main函数执行,自己创建的函数,也需要一个函数开始运行(初始函数),一旦这个函数运行完毕,线程结束		//这个进程是否执行完毕的标志是主线程是否完毕,如果主线程执行完毕了,就代表整个进程执行完毕	//如果子线程还没有执行完,那么这些子线程也会被操作系统强行终止。	//一般情况下,想保持子线程(自己创建的线程)运行的话,需要让主线程一直运行,有例外情况	//创建子线程	//1.头文件thread    标准库中的类	//2.创建函数	//3.main中写代码	//这段代码是两个线程在走,同时做两件事 即使一条线被堵住了,另一条线还可以运行	thread myobj(myprint);			  //myprint 为可调用对象         此代码(1)创建线程,线程入口 myprint函数(2)myprint线程开始执行		//myobj.join();					 //join阻塞主线程,让主线程等待子线程执行完毕,然后子线程和主线程汇合,再继续走主线程		//如果不阻塞 主线程会早于子线程完成,子线程被强制终止 	//良好的程序应该主线程等待子线程完毕后才退出	//detach():传统多线程程序主线程要等待子线程再结束  detach函数使主线程不等待子线程运行,可以早于子线程结束,各自执行各自的程序	//引入原因:线程过多,主线程一直等待 	//一旦detach(),主线程与子线程失去联系,子线程在后台运行,子线程被系统接管,子线程执行完毕后,由运行时库负责清理线程相关资源。	myobj.detach();	cout << " i love china !" << endl;	cout << " i love china !" << endl;	cout << " i love china !" << endl;	cout << " 主线程完毕 !" << endl;		return 0;}

在这里插入图片描述

1.4 joinable()函数

判断是否可以成功使用joinable或者detach ,返回true或者false。

#include "pch.h"#include <iostream>#include <thread>using namespace std;void myprint(){   	cout << "我的线程开始了" << endl;	cout << "我的线程结束了1" << endl;	cout << "我的线程结束了2" << endl;	cout << "我的线程结束了3" << endl;	cout << "我的线程结束了4" << endl;	cout << "我的线程结束了5" << endl;	cout << "我的线程结束了6" << endl;	cout << "我的线程结束了7" << endl;}int main(){   	cout << " i love china !" << endl;	//个主线程在执行,主线程从main函数返回,整个进程执行完毕	//主线程从main函数执行,自己创建的函数,也需要一个函数开始运行(初始函数),一旦这个函数运行完毕,线程结束		//这个进程是否执行完毕的标志是主线程是否完毕,如果主线程执行完毕了,就代表整个进程执行完毕	//如果子线程还没有执行完,那么这些子线程也会被操作系统强行终止。	//一般情况下,想保持子线程(自己创建的线程)运行的话,需要让主线程一直运行,有例外情况	//创建子线程	//1.头文件thread    标准库中的类	//2.创建函数	//3.main中写代码	//这段代码是两个线程在走,同时做两件事 即使一条线被堵住了,另一条线还可以运行	thread myobj(myprint);			  //myprint 为可调用对象         此代码(1)创建线程,线程入口 myprint函数(2)myprint线程开始执行		//myobj.join();					 //join阻塞主线程,让主线程等待子线程执行完毕,然后子线程和主线程汇合,再继续走主线程		//如果不阻塞 主线程会早于子线程完成,子线程被强制终止 	//良好的程序应该主线程等待子线程完毕后才退出	//detach():传统多线程程序主线程要等待子线程再结束  detach函数使主线程不等待子线程运行,可以早于子线程结束,各自执行各自的程序	//引入原因:线程过多,主线程一直等待 	//一旦detach(),主线程与子线程失去联系,子线程在后台运行,子线程被系统接管,子线程执行完毕后,由运行时库负责清理线程相关资源。	//更推荐join()  一旦detach,不能再用join	if (myobj.joinable()) //判断是否可以成功使用joinable或者detach  返回true或者false		cout << "1.joinable =true" << endl;	else		cout << "1.joinable =false" << endl;	myobj.detach();	if (myobj.joinable()) //判断是否可以成功使用joinable或者detach  返回true或者false		cout << "2.joinable =true" << endl;	else		cout << "2.joinable =false" << endl;	cout << " i love china !" << endl;	cout << " i love china !" << endl;	cout << " i love china !" << endl;	cout << " 主线程完毕 !" << endl;		return 0;}

在这里插入图片描述

判断可以加入阻塞函数后,加入阻塞函数。

#include "pch.h"#include <iostream>#include <thread>using namespace std;void myprint(){   	cout << "我的线程开始了" << endl;	cout << "我的线程结束了1" << endl;	cout << "我的线程结束了2" << endl;	cout << "我的线程结束了3" << endl;	cout << "我的线程结束了4" << endl;	cout << "我的线程结束了5" << endl;	cout << "我的线程结束了6" << endl;	cout << "我的线程结束了7" << endl;}int main(){   	cout << " i love china !" << endl;	//个主线程在执行,主线程从main函数返回,整个进程执行完毕	//主线程从main函数执行,自己创建的函数,也需要一个函数开始运行(初始函数),一旦这个函数运行完毕,线程结束		//这个进程是否执行完毕的标志是主线程是否完毕,如果主线程执行完毕了,就代表整个进程执行完毕	//如果子线程还没有执行完,那么这些子线程也会被操作系统强行终止。	//一般情况下,想保持子线程(自己创建的线程)运行的话,需要让主线程一直运行,有例外情况	//创建子线程	//1.头文件thread    标准库中的类	//2.创建函数	//3.main中写代码	//这段代码是两个线程在走,同时做两件事 即使一条线被堵住了,另一条线还可以运行	thread myobj(myprint);			  //myprint 为可调用对象         此代码(1)创建线程,线程入口 myprint函数(2)myprint线程开始执行		//myobj.join();					 //join阻塞主线程,让主线程等待子线程执行完毕,然后子线程和主线程汇合,再继续走主线程		//如果不阻塞 主线程会早于子线程完成,子线程被强制终止 	//良好的程序应该主线程等待子线程完毕后才退出	//detach():传统多线程程序主线程要等待子线程再结束  detach函数使主线程不等待子线程运行,可以早于子线程结束,各自执行各自的程序	//引入原因:线程过多,主线程一直等待 	//一旦detach(),主线程与子线程失去联系,子线程在后台运行,子线程被系统接管,子线程执行完毕后,由运行时库负责清理线程相关资源。	//更推荐join()  一旦detach,不能再用join	if (myobj.joinable()) //判断是否可以成功使用joinable或者detach  返回true或者false	{   		cout << "1.joinable =true" << endl;		myobj.join();	}	else		cout << "1.joinable =false" << endl;	//if (myobj.joinable()) //判断是否可以成功使用joinable或者detach  返回true或者false	//	cout << "2.joinable =true" << endl;	//else	//	cout << "2.joinable =false" << endl;	cout << " i love china !" << endl;	cout << " i love china !" << endl;	cout << " i love china !" << endl;	cout << " 主线程完毕 !" << endl;		return 0;}

在这里插入图片描述

二 其他创建线程的方法

1.用类对象

示例:

#include "pch.h"#include <iostream>#include <thread>using namespace std;//void myprint()//{   //	cout << "我的线程开始了" << endl;//	cout << "我的线程结束了1" << endl;//	cout << "我的线程结束了2" << endl;//	cout << "我的线程结束了3" << endl;//	cout << "我的线程结束了4" << endl;//	cout << "我的线程结束了5" << endl;//	cout << "我的线程结束了6" << endl;//	cout << "我的线程结束了7" << endl;//////}class TA{   public:	void operator()() //不能带参数 重载()调用对象就是调用函数	{   		cout << "我的线程operator开始了" << endl;	    cout << "我的线程operator结束了" << endl;		}};int main(){   	cout << " i love china !" << endl;	//个主线程在执行,主线程从main函数返回,整个进程执行完毕	//主线程从main函数执行,自己创建的函数,也需要一个函数开始运行(初始函数),一旦这个函数运行完毕,线程结束		//这个进程是否执行完毕的标志是主线程是否完毕,如果主线程执行完毕了,就代表整个进程执行完毕	//如果子线程还没有执行完,那么这些子线程也会被操作系统强行终止。	//一般情况下,想保持子线程(自己创建的线程)运行的话,需要让主线程一直运行,有例外情况	//创建子线程方法1  thread调用函数	//1.头文件thread    标准库中的类	//2.创建函数	//3.main中写代码	//这段代码是两个线程在走,同时做两件事 即使一条线被堵住了,另一条线还可以运行	//thread myobj(myprint);			  //myprint 为可调用对象         此代码(1)创建线程,线程入口 myprint函数(2)myprint线程开始执行		//myobj.join();					 //join阻塞主线程,让主线程等待子线程执行完毕,然后子线程和主线程汇合,再继续走主线程		//如果不阻塞 主线程会早于子线程完成,子线程被强制终止 	//良好的程序应该主线程等待子线程完毕后才退出	//detach():传统多线程程序主线程要等待子线程再结束  detach函数使主线程不等待子线程运行,可以早于子线程结束,各自执行各自的程序	//引入原因:线程过多,主线程一直等待 	//一旦detach(),主线程与子线程失去联系,子线程在后台运行,子线程被系统接管,子线程执行完毕后,由运行时库负责清理线程相关资源。	//更推荐join()  一旦detach,不能再用join	//if (myobj.joinable()) //判断是否可以成功使用joinable或者detach  返回true或者false	//{   	//	cout << "1.joinable =true" << endl;	//	myobj.join();	//}	//else	//	cout << "1.joinable =false" << endl;	//if (myobj.joinable()) //判断是否可以成功使用joinable或者detach  返回true或者false	//	cout << "2.joinable =true" << endl;	//else		cout << "2.joinable =false" << endl;	//cout << " i love china !" << endl;	//cout << " i love china !" << endl;	//cout << " i love china !" << endl;	//创建子线程方法2  thread调用类对象(可调用对象)	TA ta;	thread myobj(ta);	myobj.join();   	cout << " 主线程完毕 !" << endl;	return 0;}

在这里插入图片描述

使用类对象创建多线程时,如果使用detach会出现问题:当构造函数采用引用传递时,构造函数中如果使用了局部变量,主线程结束时,局部变量的地址被回收,打印出的结果不可预料。

#include "pch.h"#include <iostream>#include <thread>using namespace std;//void myprint()//{   //	cout << "我的线程开始了" << endl;//	cout << "我的线程结束了1" << endl;//	cout << "我的线程结束了2" << endl;//	cout << "我的线程结束了3" << endl;//	cout << "我的线程结束了4" << endl;//	cout << "我的线程结束了5" << endl;//	cout << "我的线程结束了6" << endl;//	cout << "我的线程结束了7" << endl;//}class TA{   public:	int &mi;	TA(int &i) :mi(i) {   }	void operator()() //不能带参数 重载()调用对象就是调用函数	{   		/*cout << "我的线程operator开始了" << endl;	    cout << "我的线程operator结束了" << endl;*/		cout << "mi1的值为:" <<mi<<endl;		cout << "mi2的值为:" << mi<< endl;		cout << "mi3的值为:" <<mi<< endl;		cout << "mi4的值为:" << mi<<endl;	}};int main(){   	cout << " i love china !" << endl;	//个主线程在执行,主线程从main函数返回,整个进程执行完毕	//主线程从main函数执行,自己创建的函数,也需要一个函数开始运行(初始函数),一旦这个函数运行完毕,线程结束		//这个进程是否执行完毕的标志是主线程是否完毕,如果主线程执行完毕了,就代表整个进程执行完毕	//如果子线程还没有执行完,那么这些子线程也会被操作系统强行终止。	//一般情况下,想保持子线程(自己创建的线程)运行的话,需要让主线程一直运行,有例外情况	//创建子线程方法1  thread调用函数	//1.头文件thread    标准库中的类	//2.创建函数	//3.main中写代码	//这段代码是两个线程在走,同时做两件事 即使一条线被堵住了,另一条线还可以运行	//thread myobj(myprint);			  //myprint 为可调用对象         此代码(1)创建线程,线程入口 myprint函数(2)myprint线程开始执行		//myobj.join();					 //join阻塞主线程,让主线程等待子线程执行完毕,然后子线程和主线程汇合,再继续走主线程		//如果不阻塞 主线程会早于子线程完成,子线程被强制终止 	//良好的程序应该主线程等待子线程完毕后才退出	//detach():传统多线程程序主线程要等待子线程再结束  detach函数使主线程不等待子线程运行,可以早于子线程结束,各自执行各自的程序	//引入原因:线程过多,主线程一直等待 	//一旦detach(),主线程与子线程失去联系,子线程在后台运行,子线程被系统接管,子线程执行完毕后,由运行时库负责清理线程相关资源。	//更推荐join()  一旦detach,不能再用join	//if (myobj.joinable()) //判断是否可以成功使用joinable或者detach  返回true或者false	//{   	//	cout << "1.joinable =true" << endl;	//	myobj.join();	//}	//else	//	cout << "1.joinable =false" << endl;	//if (myobj.joinable()) //判断是否可以成功使用joinable或者detach  返回true或者false	//	cout << "2.joinable =true" << endl;	//else		cout << "2.joinable =false" << endl;	//cout << " i love china !" << endl;	//cout << " i love china !" << endl;	//cout << " i love china !" << endl;	//创建子线程方法2  thread调用类对象(可调用对象)	int mii = 6;	TA ta(mii);	thread myobj(ta);	myobj.detach();   	cout << " 主线程完毕 !" << endl;	return 0;}

在这里插入图片描述
在这里插入图片描述

使用对象创建子线程时,thread调用对象时使用了拷贝构造函数,对象被复制到线程中去,如果对象没使用引用或指针,就不会出现问题。下面验证thread调用了对象的拷贝构造函数。

下面是使用detach验证

#include "pch.h"#include <iostream>#include <thread>using namespace std;//void myprint()//{   //	cout << "我的线程开始了" << endl;//	cout << "我的线程结束了1" << endl;//	cout << "我的线程结束了2" << endl;//	cout << "我的线程结束了3" << endl;//	cout << "我的线程结束了4" << endl;//	cout << "我的线程结束了5" << endl;//	cout << "我的线程结束了6" << endl;//	cout << "我的线程结束了7" << endl;//}class TA{   public:	int mi;	TA(int i) :mi(i)	{   		cout << "TA()构造函数被执行" << endl;		}	TA(const TA&ta) :mi(ta.mi)	{   		cout << "TA()拷贝构造函数被执行" << endl;	}	~TA()	{   		cout << "析构函数被执行" << endl;	}	void operator()() //不能带参数 重载() 作为可调用对象	{   		/*cout << "我的线程operator开始了" << endl;	    cout << "我的线程operator结束了" << endl;*/		cout << "mi1的值为:" <<mi<<endl;		cout << "mi2的值为:" << mi<< endl;		cout << "mi3的值为:" <<mi<< endl;		cout << "mi4的值为:" << mi<<endl;	}};int main(){   	cout << " i love china !" << endl;	//个主线程在执行,主线程从main函数返回,整个进程执行完毕	//主线程从main函数执行,自己创建的函数,也需要一个函数开始运行(初始函数),一旦这个函数运行完毕,线程结束		//这个进程是否执行完毕的标志是主线程是否完毕,如果主线程执行完毕了,就代表整个进程执行完毕	//如果子线程还没有执行完,那么这些子线程也会被操作系统强行终止。	//一般情况下,想保持子线程(自己创建的线程)运行的话,需要让主线程一直运行,有例外情况	//创建子线程方法1  thread调用函数	//1.头文件thread    标准库中的类	//2.创建函数	//3.main中写代码	//这段代码是两个线程在走,同时做两件事 即使一条线被堵住了,另一条线还可以运行	//thread myobj(myprint);			  //myprint 为可调用对象         此代码(1)创建线程,线程入口 myprint函数(2)myprint线程开始执行		//myobj.join();					 //join阻塞主线程,让主线程等待子线程执行完毕,然后子线程和主线程汇合,再继续走主线程		//如果不阻塞 主线程会早于子线程完成,子线程被强制终止 	//良好的程序应该主线程等待子线程完毕后才退出	//detach():传统多线程程序主线程要等待子线程再结束  detach函数使主线程不等待子线程运行,可以早于子线程结束,各自执行各自的程序	//引入原因:线程过多,主线程一直等待 	//一旦detach(),主线程与子线程失去联系,子线程在后台运行,子线程被系统接管,子线程执行完毕后,由运行时库负责清理线程相关资源。	//更推荐join()  一旦detach,不能再用join	//if (myobj.joinable()) //判断是否可以成功使用joinable或者detach  返回true或者false	//{   	//	cout << "1.joinable =true" << endl;	//	myobj.join();	//}	//else	//	cout << "1.joinable =false" << endl;	//if (myobj.joinable()) //判断是否可以成功使用joinable或者detach  返回true或者false	//	cout << "2.joinable =true" << endl;	//else		cout << "2.joinable =false" << endl;	//cout << " i love china !" << endl;	//cout << " i love china !" << endl;	//cout << " i love china !" << endl;	//创建子线程方法2  thread调用类对象(可调用对象)	//如果使用类对象创建子线程并调用了detach,主线程结束后,对象还在吗?	//对象不在了,但是对象时被复制到了线程中去,原对象被销毁但复制的对象还在,如果对象中不存在引用和指针,就不会出问题	int mii = 6;	TA ta(mii);	thread myobj(ta);	myobj.detach();   	cout << " 主线程完毕 !" << endl;	return 0;}

在这里插入图片描述

下面使用join函数做对比验证

#include "pch.h"#include <iostream>#include <thread>using namespace std;//void myprint()//{   //	cout << "我的线程开始了" << endl;//	cout << "我的线程结束了1" << endl;//	cout << "我的线程结束了2" << endl;//	cout << "我的线程结束了3" << endl;//	cout << "我的线程结束了4" << endl;//	cout << "我的线程结束了5" << endl;//	cout << "我的线程结束了6" << endl;//	cout << "我的线程结束了7" << endl;//}class TA{   public:	int &mi;	TA(int &i) :mi(i)	{   		cout << "TA()构造函数被执行" << endl;		}	TA(const TA&ta) :mi(ta.mi)	{   		cout << "TA()拷贝构造函数被执行" << endl;	}	~TA()	{   		cout << "析构函数被执行" << endl;	}	void operator()() //不能带参数 重载() 作为可调用对象	{   		/*cout << "我的线程operator开始了" << endl;	    cout << "我的线程operator结束了" << endl;*/		cout << "mi1的值为:" <<mi<<endl;		cout << "mi2的值为:" << mi<< endl;		cout << "mi3的值为:" <<mi<< endl;		cout << "mi4的值为:" << mi<<endl;	}};int main(){   	cout << " i love china !" << endl;	//个主线程在执行,主线程从main函数返回,整个进程执行完毕	//主线程从main函数执行,自己创建的函数,也需要一个函数开始运行(初始函数),一旦这个函数运行完毕,线程结束		//这个进程是否执行完毕的标志是主线程是否完毕,如果主线程执行完毕了,就代表整个进程执行完毕	//如果子线程还没有执行完,那么这些子线程也会被操作系统强行终止。	//一般情况下,想保持子线程(自己创建的线程)运行的话,需要让主线程一直运行,有例外情况	//创建子线程方法1  thread调用函数	//1.头文件thread    标准库中的类	//2.创建函数	//3.main中写代码	//这段代码是两个线程在走,同时做两件事 即使一条线被堵住了,另一条线还可以运行	//thread myobj(myprint);			  //myprint 为可调用对象         此代码(1)创建线程,线程入口 myprint函数(2)myprint线程开始执行		//myobj.join();					 //join阻塞主线程,让主线程等待子线程执行完毕,然后子线程和主线程汇合,再继续走主线程		//如果不阻塞 主线程会早于子线程完成,子线程被强制终止 	//良好的程序应该主线程等待子线程完毕后才退出	//detach():传统多线程程序主线程要等待子线程再结束  detach函数使主线程不等待子线程运行,可以早于子线程结束,各自执行各自的程序	//引入原因:线程过多,主线程一直等待 	//一旦detach(),主线程与子线程失去联系,子线程在后台运行,子线程被系统接管,子线程执行完毕后,由运行时库负责清理线程相关资源。	//更推荐join()  一旦detach,不能再用join	//if (myobj.joinable()) //判断是否可以成功使用joinable或者detach  返回true或者false	//{   	//	cout << "1.joinable =true" << endl;	//	myobj.join();	//}	//else	//	cout << "1.joinable =false" << endl;	//if (myobj.joinable()) //判断是否可以成功使用joinable或者detach  返回true或者false	//	cout << "2.joinable =true" << endl;	//else		cout << "2.joinable =false" << endl;	//cout << " i love china !" << endl;	//cout << " i love china !" << endl;	//cout << " i love china !" << endl;	//创建子线程方法2  thread调用类对象(可调用对象)	//如果使用类对象创建子线程并调用了detach,主线程结束后,对象还在吗?	//对象不在了,但是对象时被复制到了线程中去,原对象被销毁但复制的对象还在,如果对象中不存在引用和指针,就不会出问题	int mii = 6;	TA ta(mii);	thread myobj(ta);	//myobj.detach();  	myobj.join();	cout << " 主线程完毕 !" << endl;	return 0;}

在这里插入图片描述

2.用lambda表达式

#include "pch.h"#include <iostream>#include <thread>using namespace std;//void myprint()//{   //	cout << "我的线程开始了" << endl;//	cout << "我的线程结束了1" << endl;//	cout << "我的线程结束了2" << endl;//	cout << "我的线程结束了3" << endl;//	cout << "我的线程结束了4" << endl;//	cout << "我的线程结束了5" << endl;//	cout << "我的线程结束了6" << endl;//	cout << "我的线程结束了7" << endl;//}class TA{   public:	int &mi;	TA(int &i) :mi(i)	{   		cout << "TA()构造函数被执行" << endl;		}	TA(const TA&ta) :mi(ta.mi)	{   		cout << "TA()拷贝构造函数被执行" << endl;	}	~TA()	{   		cout << "析构函数被执行" << endl;	}	void operator()() //不能带参数 重载() 作为可调用对象	{   		/*cout << "我的线程operator开始了" << endl;	    cout << "我的线程operator结束了" << endl;*/		cout << "mi1的值为:" <<mi<<endl;		cout << "mi2的值为:" << mi<< endl;		cout << "mi3的值为:" <<mi<< endl;		cout << "mi4的值为:" << mi<<endl;	}};int main(){   	cout << " i love china !" << endl;	//个主线程在执行,主线程从main函数返回,整个进程执行完毕	//主线程从main函数执行,自己创建的函数,也需要一个函数开始运行(初始函数),一旦这个函数运行完毕,线程结束		//这个进程是否执行完毕的标志是主线程是否完毕,如果主线程执行完毕了,就代表整个进程执行完毕	//如果子线程还没有执行完,那么这些子线程也会被操作系统强行终止。	//一般情况下,想保持子线程(自己创建的线程)运行的话,需要让主线程一直运行,有例外情况/***********************************************************************/	//创建子线程方法1 thread调用函数	//1.头文件thread    标准库中的类	//2.创建函数	//3.main中写代码	//这段代码是两个线程在走,同时做两件事 即使一条线被堵住了,另一条线还可以运行	//thread myobj(myprint);			  //myprint 为可调用对象         此代码(1)创建线程,线程入口 myprint函数(2)myprint线程开始执行		//myobj.join();					 //join阻塞主线程,让主线程等待子线程执行完毕,然后子线程和主线程汇合,再继续走主线程		//如果不阻塞 主线程会早于子线程完成,子线程被强制终止 	//良好的程序应该主线程等待子线程完毕后才退出	//detach():传统多线程程序主线程要等待子线程再结束  detach函数使主线程不等待子线程运行,可以早于子线程结束,各自执行各自的程序	//引入原因:线程过多,主线程一直等待 	//一旦detach(),主线程与子线程失去联系,子线程在后台运行,子线程被系统接管,子线程执行完毕后,由运行时库负责清理线程相关资源。	//更推荐join()  一旦detach,不能再用join	//if (myobj.joinable()) //判断是否可以成功使用joinable或者detach  返回true或者false	//{   	//	cout << "1.joinable =true" << endl;	//	myobj.join();	//}	//else	//	cout << "1.joinable =false" << endl;	//if (myobj.joinable()) //判断是否可以成功使用joinable或者detach  返回true或者false	//	cout << "2.joinable =true" << endl;	//else		cout << "2.joinable =false" << endl;	//cout << " i love china !" << endl;	//cout << " i love china !" << endl;	//cout << " i love china !" << endl;/***********************************************************************/	//创建子线程方法2  2.1thread调用类对象(可调用对象)	//如果使用类对象创建子线程并调用了detach,主线程结束后,对象还在吗?	//对象不在了,但是对象时被复制到了线程中去,原对象被销毁但复制的对象还在,如果对象中不存在引用和指针,就不会出问题	//int mii = 6;	//TA ta(mii);	//thread myobj(ta);	myobj.detach();  	//myobj.join();	//2.2使用lambda表达式	auto lamthread = []	{   		cout << "我的线程lambda开始了" << endl;		cout << "我的线程lambda结束了" << endl;		};	thread myobj(lamthread);	myobj.join();	cout << " 主线程完毕 !" << endl;	return 0;}

在这里插入图片描述

转载地址:http://kwfr.baihongyu.com/

你可能感兴趣的文章
「初级篇」跟我一起学docker(四)--容器的基本操作
查看>>
22 岁毕业做程序员的「普通」人,50 岁时的人生轨迹是怎样的?
查看>>
『高级篇』docker之安全认证kubernetes命令熟悉(40)
查看>>
scala上界与下界、协变与逆变
查看>>
java稀疏数组
查看>>
springboot解决前后端交互跨域问题
查看>>
全球数字货币加快研发
查看>>
数字化助力金融科技,实现产业良性循环
查看>>
2020-11-18(失败的一天)
查看>>
2020-11-23(彻底理解KMP)
查看>>
DMB DSB ISB 简介
查看>>
常用的IDC函数
查看>>
BUUCTF 新年快乐 内涵的软件 Java逆向解密 刮开有奖
查看>>
虎符杯——虚拟机逆向
查看>>
angr学习笔记(7)(malloc地址单元符号化)
查看>>
angr学习笔记(9)(添加约束)
查看>>
angr学习笔记(13)(static_binary)
查看>>
windows环境利用start命令实现微信多开
查看>>
「CF149D」括号涂色 区间DP好题
查看>>
树状数组 模板总结
查看>>