线程

线程是一个基本的 CPU 执行单元,也是程序执行流的最小单位。线程也常被称为轻量级进程。

引入线程后:

对象 主要角色
进程 系统资源分配单位,例如地址空间、打开文件、I/O 资源
线程 处理机调度和分配单位

900

同一进程内的线程共享进程资源,例如地址空间、全局变量、打开文件等;但每个线程有自己的执行现场,例如线程 ID、程序计数器、寄存器、栈等。

线程和进程

角度 进程 线程
资源拥有 拥有独立地址空间和资源集合 共享所属进程资源
调度单位 传统系统中是调度单位 引入线程后成为基本调度单位
切换开销 切换地址空间和资源环境,开销较大 同进程内线程切换开销较小
通信 进程间地址空间隔离,需要 IPC 同进程线程共享地址空间,通信更方便
影响范围 一个进程崩溃通常不直接破坏其他进程 一个线程错误可能破坏同进程共享数据

同一进程内线程切换成本较低,是因为很多资源环境不需要更换;但线程共享地址空间,也意味着共享数据更容易发生竞争,后面同步与互斥会专门处理这个问题。

用户级线程

用户级线程 ULT,User-Level Thread,由应用程序和线程库管理。操作系统内核不知道这些线程的存在。

问题 用户级线程
谁管理线程 用户态线程库
切换是否进入核心态 不需要
内核是否看得见 看不见,只看到所属进程
阻塞影响 一个用户级线程阻塞,可能导致整个进程阻塞
多核并行 同一进程内多个用户级线程不能真正同时运行在多个 CPU 核上

用户级线程切换快,因为不需要进入内核态。但内核只把整个进程当作调度单位:如果该进程因为一个线程执行阻塞系统调用而阻塞,对操作系统来说就是这个进程发生了阻塞,所以线程库中的其他用户级线程也可能一起停住。

内核级线程

内核级线程 KLT,Kernel-Level Thread,由操作系统内核支持和管理。内核为线程建立 TCB,Thread Control Block,即线程控制块。

问题 内核级线程
谁管理线程 操作系统内核
切换是否进入核心态 需要
内核是否看得见 看得见,内核维护 TCB
阻塞影响 一个线程阻塞,同进程其他线程仍可运行
多核并行 多个线程可以在多核处理机上并行

内核级线程并发能力强,但线程创建、撤销、切换等工作需要内核参与,系统开销比用户级线程更大。

Important

操作系统只看得见内核级线程。因此,在支持内核级线程的系统中,真正作为处理机分配单位的是内核级线程。

# 多线程模型

用户级线程和内核级线程之间可以有不同映射关系。

900

模型 映射 优点 缺点
多对一 多个用户级线程映射到一个内核级线程 用户态切换快,管理开销小 一个线程阻塞可能阻塞整个进程,不能利用多核并行
一对一 每个用户级线程映射到一个内核级线程 一个线程阻塞不影响其他线程,可多核并行 内核级线程数量多,管理开销大
多对多 $n$ 个用户级线程映射到 $m$ 个内核级线程,且 $n \ge m$ 兼顾并发度和内核开销 实现复杂

多对多模型可以这样理解:用户级线程是代码逻辑的载体,内核级线程是运行机会的载体。一段线程代码只有映射到某个内核级线程并获得 CPU,才真正向前执行。

线程状态

线程也有类似进程的运行状态,例如就绪、运行、阻塞。区别在于,线程状态更强调执行流是否能获得 CPU;进程状态还涉及资源分配和地址空间等更大范围的管理。

在内核级线程系统中,调度程序通常围绕线程做调度;进程则作为线程共享资源的容器存在。