本文共 16951 字,大约阅读时间需要 56 分钟。
两个或者更多的任务(独立的活动)同时发生:一个程序同时执行多个独立任务。
单核cpu,某一时刻只能执行一个任务,由操作系统调度,每秒钟进行多次所谓的“任务切换”。
假象(不是真正的并发))这种切换(上下文切换)是要有时间开销的。
例如windows下的exe文件
一个可执行程序运行以后即创建了一个进程。
运行起来的可执行文件叫做一个进程。
每个进程都有一个主线程,主线程唯一。
进程存在,主线程自动存在,所以一个进程中至少含有一个主线程。
运行程序时,实际是进程的主线程来运行。共存关系。
线程:执行代码,理解成一条代码的执行路径。
除主线程外,可以通过自己写代码来创建其他线程。
每创建一个新线程,可以在同一时刻做不同的事
多线程:线程并不是越多越好,每个线程都需要一个独立的堆栈空间,线程的切换要保存很多中间状态,会耗费本该属于程序运行的时间。
线程的优点:速度快,轻量级,系统资源开销更少,执行速度更快,通信快。
缺点:有难度,要小心处理数据一致性问题。
进程间的通讯:管道 文件 消息队列 共享内存
不同电脑通信:socket
在单独的进程中,创建多个线程实现并发。
每个线程有自己独立的路径,一个进程中的所有线程共享地址内存,带来了数据一致性问题。
全局变量,指针,引用都可以在线程之间传递。
多线程开销远小于多进程。
优先考虑多线程,只谈多线程并发。
以往的多线程代码不可跨平台:
window:CreateThread(), _beginthread() ,beginthread()创建线程
Linux:pthread_create() 创建线程。
POSIX thread(pthread) 可以实现跨平台,但配置繁琐。
C++11新标准增加对多线程的支持,可移植(跨平台)
thread myobj(myprint); //myprint 为可调用对象 此代码(1)创建线程,线程入口 myprint函数(2)myprint线程开始执行
join函数阻塞主线程,让主线程等待子线程执行完毕,然后子线程和主线程汇合,再继续走主线程。
myobj.join(); //join阻塞主线程,让主线程等待子线程执行完毕,然后子线程和主线程汇合,再继续走主线程 //如果不阻塞 主线程会早于子线程完成,子线程被强制终止 //良好的程序应该主线程等待子线程完毕后才退出
下面这张图描述了主线程与子线程的通道状态,main和myprint在两个不同的线路中,如果main结束,则myprint一般情况下会被强行终止,但也有例外,下面的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;}
判断是否可以成功使用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;}
示例:
#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;}
#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/