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;
}