二线程创建结束

Posted pacino12134

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了二线程创建结束相关的知识,希望对你有一定的参考价值。

一、使用函数创建线程

1、thread

主线程从main开始,我们创建的线程也要从一个函数(初始函数)开始运行,函数结束,这个线程结束;

主线程执行完毕,代表整个进程执行完毕;

如果子线程还没执行完毕,一般情况下,这些子线程会被强行终止;

1.#include <iostream>
2.#include <string>
3.#include <thread> //线程
4using namespace std;
56//创建的线程,也就是一个初始函数
7void myprint()
8.    cout<<"1 begin" <<endl;
9.    cout<<"2 end"<<endl;
101112int main()
13.    thread myobj(myprint);//创建线程,线程就已经开始执行了
14.    myobj.join();//阻塞主线程,让主线程等子线程执行完,然后主线程继续往下走
15//如果不写join,可能main先执行完了,子线程还没执行完,会报错
16.    cout<<"main end"<<endl;
17return 0;
18

技术图片

2、detach

一般情况主线程要等子线程都执行完在继续,也有例外。

detach函数:分离,主线程不用等子线程了,主线程你执行你的,子线程我执行我的,不汇合了。(一般不用detach)

原因:创建了很多子线程,让主线程逐个等待子线程结束不太好,就提出了detach。

一点detach只有,这个thread对象就失去了与主线程的联系,这些子线程就会驻留在后台运行,由c++运行时库接管,子线程结束后,运行时库负责清理线程相关的资源(守护线程)。

 1 1.#include <iostream>  
 2 2.#include <thread> //线程  
 3 3.using namespace std;  
 4 4.  
 5 5.//创建的线程,也就是一个初始函数  
 6 6.void myprint()  
 7 7.    cout<<"1 begin" <<endl;  
 8 8.    cout<<"2 end"<<endl;  
 9 9.  
10 10.  
11 11.int main()  
12 12.    thread myobj(myprint);//创建线程,线程就已经开始执行了  
13 13.    myobj.detach();  
14 14.    cout<<"main end"<<endl;  
15 15.    return 0;  
16 16.  

一旦用了detach,就不能再用join了。

3、joinable()

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

一般可以用在使用join或detach之前,用来提前先判断,如果true,就使用true或detach;否则就不能使用join或detach函数。

二、用类创建线程

用类对象创建线程,这个对象实际上是被复制到线程中的,执行完主线程后,这个类对象会被销毁,但是复制的这个对象依旧存在,直到这个子线程结束,只要你这个类对象里面没有引用、指针,就不会产生问题。

当类对象里面有引用时:

 1 #include <iostream>
 2 #include <thread> //线程
 3 using namespace std;
 4 
 5 class TA
 6 public:
 7     int &m_i;//引用
 8     TA(int &i):m_i(i)//构造函数,引用i
 9     void operator()() //可以实现将对象当函数来使用
10         cout<<"m_i的值为"<<m_i<<endl;
11     
12 ;
13 
14 int main()
15     int a=9;
16     TA ta(a);//引用a
17     thread myobj(ta);//ta为可调对象,
18     myobj.detach();
19     //这个时候使用detach的话,有可能主线程先执行完,那么a被销毁,由于TA是引用,也就是指向了一个已经销毁的内存,会出错的,只能用join
20     cout<<"main end"<<endl;
21     return 0;
22 

如果主线程先执行完,那么a被销毁,TA的成员变量是引用类型的,也就是子线程使用的是一个指向(引用是特殊的指针)了一个已经回收的地址,类似于野指针,就会出错,所以不要用detach。

改成join后,分析代码:创建ta对象:

  1. 创建类对象ta,构造函数被执行;
  2. 创建线程myobj,里面的ta对象复制给线程myobj,复制的ta对象构造函数执行;
  3. 执行线程,主线程等待子线程结束;
  4. 子线程myobj结束,复制的ta对象执行析构函数;
  5. 主线程继续执行 main end;
  6. main函数代码跑完了,主线程执行完毕,ta对象析构函数执行,释放内存和变量a;

三、用lambda表达式

 1 #include <iostream>
 2 #include <thread> //线程
 3 using namespace std;
 4 
 5 int main()
 6     auto mythread = []
 7         cout<<"我的子线程开始了"<<endl;
 8         cout<< "结束了"<<endl;
 9     ;
10     thread myobj(mythread);
11     myobj.join();
12     cout<<"main end"<<endl;
13     return 0;
14 

 

TA构造函数执行,创建线程myobj,这个ta对象时复制进去的,所以这个

 

以上是关于二线程创建结束的主要内容,如果未能解决你的问题,请参考以下文章

父线程 在创建了子线程后,是否继续执行自己的代码?它可以在子线程结束前 结束吗?

C++并发与多线程 2_线程启动结束,创建线程多种方法,join,detach

Python 线程创建和传参

线程的创建与结束

java线程复习1(线程创建)

python 包之 threading 多线程教程