线程的实现方式
用户级线程
历史背景:早期操作系统只支持进程,不支持线程,当时的线程是由线程库实现的
本质:从代码角度来看,线程其实就是一段代码逻辑
int main() { int i = 0; while(true) { if(i == 0) {处理视频聊天的代码;} if(i == 1) {处理视频聊天的代码;} if(i == 2) {处理视频聊天的代码;} i = (i+1) % 3; } }
在上面这段代码中,while循环就相当于一个“线程库”,它完成了对线程的管理工作(调度即函数调用):在进入while循环后,由于取模运算的特性,i的值会在0,1,2之间无限循环直到在线程的运行过程中出现了比如break等操作才会结束
注意事项:1、用户级线程的管理工作由线程库来完成,所有的线程管理工作都由应用程序负责
2、用户级线程中,线程切换可以在用户态下完成,无序操作系统的干预进行CPU变态
3、操作系统不能意识到用户级线程的存在(只有用户才能感知到用户级线程的存在)
优点:用户级线程的切换在用户空间即可完成,不需要切换到核心态,线程管理的系统开销小,效率高
缺点:当一个用户级线程被阻塞后,整个进程都会被阻塞,并发度不高,多个线程不可以在多核处理机上并行运行(此时CPU还是给进程分配系统资源的)
内核级线程
大多数现代操作系统都实现了,内核级线程
注意事项:1、内核级线程的管理工作由操作系统内核完成
2、内核级线程中,线程调度、切换等操作由内核负责,必须要在核心态下完成,所以需要操作系统干预从而进行CPU变态
3、操作系统会为每个内核级线程建立相应的TCB,通过TCB对线程进行管理,它是操作系统能看到的线程
优点:当一个线程被阻塞后,别的线程还可以继续执行,并发能力强,多线程可以在多核处理机上执行(内核级线程是处理机调度的基本单位,进程是分配资源的基本单位,在多核CPU的环境下,这些内核级线程可以被分配到不同的核心下并发执行,不同的内核级线程中又可以跑不同的代码逻辑)
缺点:一个用户进程会占用多个内核级线程,线程切换由操作系统内核完成,需要切换到核心态,因此线程管理成本高,开销大(变态销毁内存空间)
多线程模型
在支持内核级线程的程序中,根据用户级线程和内核级线程的映射关系,可以划分为几种多线程模型:
一对一模型
特点:一个用户级线程映射到一个内核级线程,每个用户进程有与用户级线程同数量的内核级线程
优点:当一个线程被阻塞后,其余线程还可以继续执行,并发能力强,多线程可以在多核处理机上并行执行
缺点:一个用户进程会占用多个内核级线程,线程切换由操作系统内核完成,需要切换到核心态,因此线程管理成本高,开销大
多对多模型
特点:多个用户级线程映射到一个内核级线程,且一个线程只被分配一个内核级线程
优点:用户级线程的切换在用户空间即可完成,不需要切换到核心态,线程管理的系统开销小,效率高
缺点:当一个用户级线程被阻塞后,整个进程都会被阻塞,并发程度不高,且多线程不可在多核处理机上并行运行(一个线程只被分配一个内核级线程)
注意事项:操作系统只能看见内核级线程,因此只有内核级线程才是处理机分配的单位
多对多模型
特点:n个用户级线程映射到m个内核级线程(n>=m),每个用户进程对应m个内核级线程,克服了多对一模型并发度不高的缺点,又克服了一对一模型中一个用户进程占用太多内核级线程,系统资源开销过大的缺点
注意事项:1、用户级线程是“代码逻辑”的载体,内核级线程是“运行机会”的载体
2、内核级线程才是处理机分配的基本单位,多核CPU环境下,上图的进程最多被分配两个核
3、一段“代码逻辑”只有获得了“运行机会”才会被CPU执行
4、内核级线程中可以运行任意一个有映射关系的用户级线程中,只有连个内核级线程中正在运行的“代码逻辑”均阻塞时,改进程才会阻塞:
本节思维导图
~over~