std::thread obj(MyPrint); //创建了线程,线程入口函数MyPrint(),然后MyPrint()函数开始执行。
创建线程主要包含以下几步:
包含一个头文件thread。
线程入口初始函数要写。
入口初始函数是一个可以调用的对象。一组可以执行的语句称为可调用对象,C++中可调用对象可以是函数、函数指针、lambda表达式、bind绑定对象、还可以是重载了()的类对象( operator() )。
必须要明白:有两个线程在跑,相当于整个程序中有两条线在同时走,即使一条被阻塞,另一条也能运行。
thread是一个标准库的类。
obj.join(); //阻止主线程执行,而是等待子线程执行完毕join()才算执行完毕,然后才执行主线程。
就是阻塞,阻塞主线程,让主线程等待子线程执行完毕,然后子线程和主线程汇合,在执行主线程代码。**
一个良好的线程程序,应该是主线程等待子线程执行完毕之后,主线程才退出来。
obj.detach(); //主线程与子线程分离开来,就是主线程自己执行自己的主线程代码,子线程执行自己的子线程代码,主线程不必等待子线程运行结束。
detach():主线程与子线程分离开来,就是主线程自己执行自己的主线程代码,子线程执行自己的子线程代码,主线程不必等待子线程运行结束。
为什么引入detach():假如创建了许多子线程,让主线程逐个等待子线程结束,一般这种情况是不友好的,所以引入了detach()。一旦detach() 之后,与这个主线程关联的thread对象就会失去与主线程之间的关联,此时的子线程就会驻留在后台运行(主线程与子线程失去联系)。
这个子线程就相当于被C++运行时库接管,当这个子线程执行完成后,就会由C++运行时库负责清理该线程相关的资源。(守护进程)
detach()使线程入口函数(子线程)失去对于自己的控制。
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ETlFrVsN-1667578384042)(C:\Users\hp\AppData\Roaming\Typora\typora-user-images\image-20221012222049292.png)]](https://1000bd.com/contentImg/2024/04/29/183d482b49962ff8.png)
#include
#include
void MyPrint(){
std::cout<<"子线程开始--->"<"<"<"<"<"<"<"<"<"<"< 输出结果:
主线程结束1
主线程结束2
主线程结束3
主线程结束4
子线程开始--->
子线程结束1--->
子线程结束2--->
子线程结束3--->
子线程结束4--->
子线程结束5--->
子线程结束6--->
子线程结束7--->
子线程结束8--->
子线程结束9--->
子线程结束10--->
主线程结束5
主线程结束6
PS C:\Users\Administrator\Desktop\thread\build\thread\Debug>
入口初始函数是一个可以调用的对象。一组可以执行的语句称为可调用对象,C++中可调用对象可以是函数、函数指针、lambda表达式、bind绑定对象、还可以是重载了opetator()成员函数的类对象( operator() )。
#include
#include
class A{
public:
void operator()(){
std::cout<<"子线程开始1"< 输出结果:
PS D:\C++11多线程代码编写\build\thread线程创建方法2\Debug> .\main.exe
子线程开始1
子线程结束1
主线程结束
PS D:\C++11多线程代码编写\build\thread线程创建方法2\Debug>
#include
#include
template
class A{
public:
A(T& a)
:a_(a)
{}
~A(){}
void operator()(){
std::cout<<"子线程开始1"< a(b);
std::thread obj(a);
//obj.join();
obj.detach();
std::cout<<"主线程结束1"< 这时会发现输出结果会有不一样的结果:
主线程结束2
主线程结束3
主线程结束4
主线程结束5
主线程结束6
主线程结束7
主线程结束8
主线程结束9
主线程结束10子线程开始1
子线程结束1
a_1的值:
主线程结束1
主线程结束2
主线程结束3
主线程结束4
主线程结束5
主线程结束6
主线程结束7
主线程结束8
主线程结束9
主线程结束10
子线程开始1
主线程结束1
主线程结束2
主线程结束3
主线程结束4
主线程结束5
主线程结束6子线程开始1
子线程结束1
a_1的值:
主线程结束7
主线程结束810
a_2的值:10
a_3的值:10
a_4的值:10
a_5的值:10
主线程结束9
主线程结束10
PS D:\C++11多线程代码编写\build\thread线程创建方法2\Debug>
#include
#include
template
class A{
public:
A(T a)
:a_(a)
{}
~A(){}
void operator()(){
std::cout<<"子线程开始1"< a(b);
std::thread obj(a);
//obj.join();
obj.detach();
std::cout<<"主线程结束1"< 输出结果:
PS D:\C++11多线程代码编写\build\thread线程创建方法2\Debug> .\main.exe
主线程结束1
主线程结束2
主线程结束3
子线程开始1主线程结束4
主线程结束5
主线程结束6
主线程结束7
子线程结束1
a_1的值:
主线程结束810
a_2的值:10
a_3的值:10
a_4的值:10
a_5的值:10
主线程结束9
主线程结束10
PS D:\C++11多线程代码编写\build\thread线程创建方法2\Debug>
其实可能还有一个疑问,对象a也是一个局部对象,当主线程main函数先于子线程结束的时候,那么对象也被销毁了,那为啥上面代码后面也还能执行后续代码呢?
#include
#include
template
class A{
public:
A(T a)
:a_(a){
std::cout<<"A的构造函数"< a(b);
std::thread obj(a);
//obj.join();
obj.detach();
std::cout<<"主线程结束1"< 输出结果:
A的构造函数
A1的拷贝构造
主线程结束1
主线程结束2
主线程结束3
主线程结束4
主线程结束5
主线程结束6
主线程结束7
主线程结束8
主线程结束9
主线程结束10子线程开始1
子线程结束1
a_1的值:
A的析构函数
PS D:\C++11多线程代码编写\build\thread线程创建方法2\Debug>
#include
#include
int main(){
auto lambadThread=[](){
std::cout<<"子线程开始1"< 输出结果:
PS D:\C++11多线程代码编写\build\thread线程创建方法3\Debug> .\main.exe
子线程开始1
子线程结束1
子线程结束2
子线程结束3
子线程结束4
主线程结束1
PS D:\C++11多线程代码编写\build\thread线程创建方法3\Debug>