首先我们知道程序就是在硬盘中的可执行文件
那么什么是线程呢?
- 在一个程序里的多个执行路线就叫做线程(thread)。更准确的定义是:线程是“一个进程内部的控制序列”
- 一切进程至少都有一个执行线程
- 进程是资源分配的基本单位,线程是cpu调度的基本单位
接着我们来稍微了解一下CPU执行中的时间片轮转机制(随机轮片)
以最早的来举例子:单核心,单线程(时间量子、时间单位)CPU只需要花1MS就可以跑完一个线程。
1秒 = 1000毫秒,因此我们在1秒内可以执行非常非常多的线程。
而运行一个线程的经历的时间随机的,并且运行次数也是随机的,。
CPU不能保证平均分配(这个是指执行时间上,执行次数上),但是可以保证所有线程都会至少走一遍,这个就是时间片轮转机制的公平性
fork和创建新线程的区别
- 当一个进程执行一个fork调用的时候,会创建出进程的一个新拷贝,新进程将拥有它自己的变量和它自己的PID。这个新进程的运行时间是独立的,它在执行时几乎完全独立于创建它的进程
- 在进程里面创建一个新线程的时候,新的执行线程会拥有自己的堆栈(因此也就有自己的局部变量),但要与它的创建者共享全局变量、文件描述符、信号处理器和当前的子目录状态
线程的优点
- 创建一个新线程的代价要比创建一个新进程小得多
- 与进程之间的切换相比,线程之间的切换需要操作系统做的工作至少在理论上要少很多
线程占用的资源要比进程少很多
线程函数库
- 与线程有关的函数构成了一个完整的系列,绝大多数函数的名字都是以“pthread_”打头的
- 要使用这些函数库,要通过引入头文件<pthread.h>
- 链接这些线程函数库时要使用编译器命令的“-lpthread”选项(VS2019之前的版本是这个命令)
- 但是在VS2019之后不是请看下面的操作:
pthread_create函数(2-1)
作用:创建一个新的线程
返回0则说明创建成功,其他结果都为失败
pthread_t pthreadid = 0;//我们先定义一个空的线程标识符,将其的地址放入这个函数,让这个函数向这个地址填充线程标识符
thread:指向 pthread_t 类型的指针,用于存储新线程的标识符,我们把前面创建的线程标识符的指针放进来就可以静静的等待线程的创建,如果成功就可以直接使用这个标识符。 attr:指向 pthread_attr_t 类型的指针,用于设置新线程的属性,通常可以设置为 NULL,表示使用默认属性。 start_routine:指向一个函数的指针,这个函数用于新线程的入口点。它的返回类型是 void *,参数类型也是 void *,即一个指针,表示任意类型的参数。新线程将从这个函数开始执行。这个就类似于QT线程中的Run函数,也就是我们创建线程之后,这个线程要做什么事情我们就在这个函数里面实现 arg:传递给 start_routine 函数的参数,类型为 void *。这个是我们的主线程和创建出来的线程之间通信的方法,我们可以传递任意的参数给子进程,不传递就设置为NULL,该参数也是一个无类型的指针 |
当我们在VS2019编写完代码去linux进行编译时,我们要注意,这边不是和之前一样,因为这个是多线程的代码,我们需要在编译前多加一个关键字
随机轮片的线程的演示
#include<iostream>
#include<pthread.h>
#include<stdio.h>
#include<unistd.h>
using namespace std;
int i = 0;
//线程执行的函数,就像是QT中的Run函数
void* pthread_function(void *arg)
{
//这边创建一个局部变量
int x = *((int*)arg);
while (1)
{
x++;
cout << "pthread_function running... x= " <<x<< endl;
sleep(1);
}
return NULL;
}
void* pthread_function2(void* arg)
{
//这边创建一个局部变量
int y = *((int *)arg);
while (1)
{
y+=2;
cout << "pthread_function22222222 running... y =" << y << endl;
sleep(1);
}
return NULL;
}
//------以上是为了验证多条线程之间的局部变量不互相影响
int main()
{
pthread_t pthreadid = 0;
if (pthread_create(&pthreadid, NULL, pthread_function, &i) != 0)//返回0就是成功,不是0就是失败,但是这个失败有好几种情况
{
perror("线程创建失败");
}
pthread_t pthreadid2 = 0;
if (pthread_create(&pthreadid, NULL, pthread_function2, &i) != 0)//返回0就是成功,不是0就是失败,但是这个失败有好几种情况
{
perror("线程创建失败");
}
while (1)
{
cout << "主进程执行线程 i =" <<i<< endl;
sleep(1);
}
return 0;
}