一、线程概念
线程是啥?先来简单了解一下:
进程?先来简单了解一下:
这里只是意会一下,不是说进程就只有一个PCB+进程地址空间而已(进程 = 内核数据结构 + 可执行程序),这样画是比较简单示意。
创建进程:进程创建的时空成本是较高的,有各种数据结构的创建,数据的加载。
如地址空间就是父子进程各有一个:
文件系统也是需要各有一个的:
关于这一点,进程地址空间和文件系统这两个文章中都可见端倪,上面两个图都是从这两个文中拿来的(文章都很短,如果有兴趣可以翻翻)。
创建线程:地址空间和地址空间上的虚拟地址,本质是一种“资源”,是资源就可以共享。
将代码分成几份,并创建对应个数的PCB,分别执行不同的代码区,就可以将串行执行变成了并发执行了。
我们的代码在进程中,全都是串行调用的,创建进程,是为了多执行流并发执行,所以创建进程和创建线程都可以,但是显然创建一个线程的成本要低得多啊!
2. linux 对线程的设计
操作系统(OS)要对线程进行管理——先描述,再组织。
下面我们来看,描述线程的结构体:
描述线程的结构体中要有各种信息,如对应的进程,线程标识符,线程优先级,上下文状态等,大概就如下:
我们觉得这样还是复杂,而且我们发现,线程中的很多信息是和进程的重合的,所以Linux的设计者认为,进程和线程都是执行流,有很高的相似性,没必要单独设计数据结构和算法,可以直接复用代码,使用进程来模拟线程。如下:
3. 线程
所以,我们可以了解到线程:
线程是进程内部的一个执行分支,线程在进程的地址空间内运行。
线程是CPU调度的基本单位。
CPU调度是让PCB排队的,现在线程就是复用的进程的PCB, 所以CPU是可以调度一个个线程的。
二、进程和线程
1. 进程和线程的关系
进程是承担分配系统资源的基本实体,而线程是进程内的一个执行分支。所以线程算是包含在进程中的。
2. 进程的调度
CPU不关心你是进程还是线程,按正常的调度算法执行就行了(当然有些属于线程、进程的细节会区别处理)。
3. 轻量级进程
从上面,我们可以看到,CPU调度的执行流要么就是进程,要不就是线程。
对于Linux来说,所有的调度执行流都叫做轻量级进程,不区分进程和线程了。在Linux中,线程是用进程模拟的,在CPU看来,看到的PCB都比传统的进程更轻量化,所以叫“轻量级进程”。
对于操作系统,进程内部只有一个执行流,那这个执行流就叫进程:
进程内部有多个执行流,那每个执行流都叫做线程:
三、pthread库
1. pthread 库的作用
上面我们说过了,Linux中线程是用进程模拟而成的,那么使用的时候就会跟纯粹的线程使用有区别。
在用户层,用户只认识进程和线程,用户可不管你底层是怎么封装的,用户我就只会用线程,可不会用什么用进程模拟的线程。
在内核层,我的线程是用进程模拟的,所有的在我这里都叫轻量级进程,我提供的也是轻量级进程的接口。
所以,就需要一个中间层,将内核有的和用户需求的连接起来。这就是pthread库的作用。
2. 手动链接 pthread库
多线程程序,都要链接pthread库。因为转换的方法都在这个库中,如果不链接这个库,那程序中用到的线程函数根本找不到。
其实我们使用库函数也是有链接C/C++的库的,但是因为我们使用的编译器gcc和g++是编译C/C++的,所以形成可执行程序时自动就链接C/C++的库了,所以我们不用手动链接。
但线程的库可不是必须的,用不到线程部分的程序在编译时就不需要链接原生线程库,你用线程的才需要这个库,所以既然不是必须的,那就交给用户手动链接了。
四、创建线程
1. pthread_create()
想创建一个新线程,使用的是pthread_create()接口。
2. 函数的使用
pthread_create(&rid,nullptr,pfunc,(void*)
