2.2 线程与多线程模型
引入线程的目的,线程与进程的比较,线程的属性与状态,用户级线程与内核级线程两种实现方式,多对一、一对一、多对多三种多线程模型。
线程的基本概念
引入进程的目的是更好地使多道程序并发执行,提高资源利用率和系统吞吐量;而引入线程的目的则是减小程序在并发执行时所付出的时空开销,提高操作系统的并发性能。
线程最直接的理解就是”轻量级进程”,它是一个基本的 CPU 执行单元,也是程序执行流的最小单元,由线程 ID、程序计数器、寄存器集合和堆栈组成。线程是进程中的一个实体,是被系统独立调度和分派的基本单位,线程自己不拥有系统资源,只拥有一点儿在运行中必不可少的资源,但它可与同属一个进程的其他线程共享进程所拥有的全部资源。
引入线程后,进程的内涵发生了改变:进程只作为除 CPU 外的系统资源的分配单元,而线程则作为处理机的分配单元。
线程与进程的比较
| 方面 | 进程 | 线程 |
|---|---|---|
| 调度 | 传统 OS 中是调度的基本单位,每次调度都要进行上下文切换,开销较大 | 引入线程的 OS 中,线程是独立调度的基本单位;同一进程中的线程切换不会引起进程切换,开销小;不同进程中的线程切换会引起进程切换 |
| 并发性 | 进程之间可以并发 | 一个进程中的多个线程之间也能并发,甚至不同进程中的线程也能并发 |
| 拥有资源 | 进程是系统中拥有资源的基本单位 | 线程不拥有系统资源(仅有一点必不可少、能保证独立运行的资源),但可以访问其隶属进程的系统资源 |
| 独立性 | 每个进程都拥有独立的地址空间和资源,除了共享全局变量,不允许其他进程访问 | 某进程中的线程对其他进程不可见;同一进程中的不同线程是为了提高并发性及进行相互之间的合作而创建的,它们共享进程的地址空间和资源 |
| 系统开销 | 创建或撤销进程时,系统都要为之分配或回收 PCB 及其他资源,开销大 | 线程切换时只需保存和设置少量寄存器内容,开销很小;同一进程内的线程共享地址空间,同步与通信非常容易实现,甚至无须操作系统的干预 |
| 多处理机 | 单线程进程只能运行在一个处理机上 | 多线程进程可以将进程中的多个线程分配到多个处理机上执行 |
线程的属性:线程是一个轻型实体,它不拥有系统资源,但每个线程都应有一个唯一的标识符和一个线程控制块(TCB),TCB 记录了线程执行的寄存器和栈等现场状态;不同的线程可以执行相同的程序;同一进程中的各个线程共享该进程所拥有的资源;线程是处理机的独立调度单位,多个线程是可以并发执行的;一个线程被创建后,便开始了它的生命周期,直至终止,线程在生命周期内会经历阻塞态、就绪态和运行态等各种状态变化。
线程的实现方式
用户级线程(ULT)
在用户级线程中,有关线程管理(创建、撤销和切换等)的所有工作都由应用程序在用户空间中完成,内核意识不到线程的存在。应用程序可以通过使用线程库设计成多线程程序。
- 优点:① 线程切换不需要转换到内核空间,节省了模式切换的开销;② 调度算法可以是进程专用的,不同的进程可根据自身的需要,对自己的线程选择不同的调度算法;③ 用户级线程的实现与操作系统平台无关,对线程管理的代码是属于用户程序的一部分;
- 缺点:① 系统调用的阻塞问题,当线程执行一个系统调用时,不仅该线程被阻塞,而且进程内的所有线程都被阻塞;② 不能发挥多处理机的优势,内核每次分配给一个进程的仅有一个 CPU,因此进程中仅有一个线程能执行。
内核级线程(KLT)
在操作系统中,无论是系统进程还是用户进程,都是在操作系统内核的支持下运行的,与内核紧密相关。内核级线程同样也是在内核的支持下运行的,线程管理的所有工作也是在内核空间内实现的。内核空间也为每个内核级线程设置一个线程控制块,内核根据该控制块感知某线程的存在,并对其加以控制。
- 优点:① 能发挥多处理机的优势,内核能同时调度同一进程中的多个线程并行执行;② 如果进程中的一个线程被阻塞,内核可以调度该进程中的其他线程占用处理机,也可运行其他进程中的线程;③ 内核支持线程具有很小的数据结构和堆栈,线程切换比较快、开销小;④ 内核本身也可采用多线程技术,可以提高系统的执行速度和效率;
- 缺点:同一进程中的线程切换,需要从用户态转到核心态进行,系统开销较大。这是因为用户进程的线程在用户态运行,而线程调度和管理是在内核实现的。
多线程模型
有些系统同时支持用户线程和内核线程,由于用户级线程和内核级线程连接方式的不同,从而形成了下面三种不同的多线程模型:
即时练习
- 1(408 真题 2011)在支持多线程的系统中,进程 P 创建的若干线程不能共享的是( )。
- 2(408 真题 2012)下列关于进程和线程的叙述中,正确的是( )。
- 3(408 真题 2019)下列关于线程的描述中,错误的是( )。
- 4采用"多对一"多线程模型的进程中,若某一线程执行了阻塞的系统调用,则( )。
标记完成后,侧栏会显示进度。进度仅保存在本浏览器中。