什么是进程?
我们可以简单的理解为一段程序的执行过程,就是exe文件的执行,且一个进程有且仅有一个主线程,也可以有多个子线程。
什么是线程?
线程可以理解为代码运行的一个通道。就好比是我们去旅游,起点和终点已经确认了,从起点到终点的中间过程就是所谓的‘线程’。
而这里我们主要讨论c++的多线程。
这里要先添加头文件thread
线程的创建:
这里要先明白,每一个线程都只能执行一种方法,而这种方法则是用函数来封装的。线程的创建有多种方法,这里主要介绍以下几种:
1.普通函数:
#include<iostream>
#include<thread>//线程库
using namespace std;
void print1()//线程处理函数,也就是我要这个线程干些什么事
{
for (int i = 0; i < 5; i++)
{
cout << "子线程1执行中" << endl;;
}
}
void text1()
{
//创建一个线程,通过构造函数将线程处理函数传给线程
thread t1(print1);
//子线程的执行方式有两种,一种是依附于主线程,主线程结束,子线程无论是否运行完都会结束,采用join函数
//join函数堵塞主线程,等待子线程完成后,再回到主线程中。一个线程只能join一次
t1.join();
}
void text2()
{
thread t1(print1);
//一种是与主线程并行存在,不依赖于主线程,各自运行各自的,子线程不会因为主线程的结束而结束,采用detach()
t1.detach();
}
int main()
{
text2();
for (int i = 0; i < 10; i++)
{
cout << "主线程执行" << endl;
}
return 0;
}
join函数运行效果如下:
先执行子线程,在执行主线程。
detach函数运行效果如下:
这里我们可以看到主线程运行过程中穿插着子线程的运行,所以子线程和主线程是各自运行的。
(注意1:这里我们要理解在单核cpu中,所谓的多线程只是一种假象,是cpu来换切换的效果,只是切换的速度很快,所以就给我们一种多个线程同时运行的效果。而在多核cpu中,则是真正的同时运行)
(注意2:detach和join不能同时处理同一个线程的状态,就是一个线程不可以同时使用join和detach)
2.类和对象(类似于仿函数):
#include<iostream>
#include<thread>//线程库
using namespace std;
class person
{
public:
void operator()()//通过重载()运算符的方式,类似于仿函数
{
for(int i=0;i<5;i++)
cout << "子线程执行" << endl;
}
};
int main()
{
thread t((person()));//通过类创建,注意这里要用()把person()括起来,不然编译器会认为这是一个函数的执行
//person p;
//thread t(p);//通过对象创建
t.join();
for (int i = 0; i < 10; i++)
{
cout << "主线程执行" << endl;
}
return 0;
}
运行效果如下:
3.lambda表达式:
#include<iostream>
#include<thread>//线程库
using namespace std;
int main()
{
thread t([]() {//这里就是利用lambad表达式当作线程处理函数使用,可以提高代码编写效率,但是代码可读性较差
for (int i = 0; i < 5; i++)
cout << "子线程执行" << endl;
});
t.join();
for (int i = 0; i < 10; i++)
{
cout << "主线程执行" << endl;
}
return 0;
}
运行效果如下:
4.利用构造函数带参数创建:
#include<iostream>
#include<thread>//线程库
using namespace std;
void print(int num)
{
for(int i=0;i<5;i++)
cout << "子线程" << num++ << endl;
}
int main()
{
int num=1;
thread t(print, num);
t.join();
for (int i = 0; i < 10; i++)
{
cout << "主线程执行" << endl;
}
return 0;
}
运行效果如下:
5.用类的成员函数去充当线程处理函数:
#include<iostream>
#include<thread>//线程库
using namespace std;
class person
{
public:
void print()//自定义成员函数
{
for (int i = 0; i < 5; i++)
cout << "子线程"<< endl;
}
};
int main()
{
person p;//创建类对象
thread t1(&person::print,p);//这里通过类名获取成员函数print,之后取地址充当线程处理函数,同时还要指明这个成员函数是哪个对象的。
t1.join();
for (int i = 0; i < 10; i++)
{
cout << "主线程执行"<< endl;
}
return 0;
}
运行效果如下:
获取线程id:
通过在线程函数处理函数中调用this_thread::get_id()函数。
#include<iostream>
#include<thread>//线程库
using namespace std;
void print(int num)
{
cout << "子线程id:" << this_thread::get_id() << endl;
for(int i=0;i<5;i++)
cout << "子线程" << (num)++ << endl;
}
int main()
{
int num = 0;
thread t1(print, num);
t1.join();
cout << "主线程id:" << this_thread::get_id() << endl;
for (int i = 0; i < 10; i++)
{
cout << "主线程执行"<< endl;
}
return 0;
}
运行效果如下: