二线程创建结束
Posted pacino12134
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了二线程创建结束相关的知识,希望对你有一定的参考价值。
一、使用函数创建线程
1、thread
主线程从main开始,我们创建的线程也要从一个函数(初始函数)开始运行,函数结束,这个线程结束;
主线程执行完毕,代表整个进程执行完毕;
如果子线程还没执行完毕,一般情况下,这些子线程会被强行终止;
1.#include <iostream> 2.#include <string> 3.#include <thread> //线程 4.using namespace std; 5. 6.//创建的线程,也就是一个初始函数 7.void myprint() 8. cout<<"1 begin" <<endl; 9. cout<<"2 end"<<endl; 10. 11. 12.int main() 13. thread myobj(myprint);//创建线程,线程就已经开始执行了 14. myobj.join();//阻塞主线程,让主线程等子线程执行完,然后主线程继续往下走 15. //如果不写join,可能main先执行完了,子线程还没执行完,会报错 16. cout<<"main end"<<endl; 17. return 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对象:
- 创建类对象ta,构造函数被执行;
- 创建线程myobj,里面的ta对象复制给线程myobj,复制的ta对象构造函数执行;
- 执行线程,主线程等待子线程结束;
- 子线程myobj结束,复制的ta对象执行析构函数;
- 主线程继续执行 main end;
- 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对象时复制进去的,所以这个
以上是关于二线程创建结束的主要内容,如果未能解决你的问题,请参考以下文章
父线程 在创建了子线程后,是否继续执行自己的代码?它可以在子线程结束前 结束吗?