5. 线程

1. 线程的定义 & 引入的原因

线程是一个基本的 CPU 执行单元,也是程序执行流的最小单位

引入线程后,不仅是进程之间可以并发,进程内的各线程之间也可以并发,从而进一步提升了系统的并发度,使得一个进程内也可以并发处理各种任务(如 QQ视频、文字聊天,传文件等等)

引入线程后,进程只作为除 CPU 之外的系统资源的分配单元(如打印机、内存地址空间等都是分配给进程的);线程作为处理机的分配单元

引入线程后的变化:

  1. 资源分配、调度

    • 传统进程机制中,进程是资源分配、调度的基本单位

    • 引入线程后,进程是资源分配的基本单位,线程是调度的基本单位

  2. 并发性

    • 传统进程机制中,只能进程间并发

    • 引入线程后,各线程之间也能并发,提升了并发度

  3. 系统开销

    • 传统的进程间并发,需要切换进程的运行环境,系统开销很大

    • 线程间并发,如果是同一个进程内的线程切换,则不需要切换进程环境,系统开销小

    • 引入线程后,并发所带来的系统开销减小

2. 线程的属性

  • 线程是处理机调度的单位

  • 多 CPU 计算机中,各个线程可占用不同的 CPU

  • 每个线程都有一个线程 ID,线程控制块 TCB

  • 线程也有就绪、阻塞、运行三种基本状态

  • 线程几乎不拥有系统资源

  • 同一进程的不同线程间共享进程的资源

  • 由于共享内存地址空间,同一进程中的线程间通信甚至无需系统干预

  • 同一进程中的线程切换,不会引起进程切换

  • 不同进程中的线程切换,会引起进程切换

  • 切换进程内的线程,系统开销很小

  • 切换进程,系统开销很大

3. 线程实现方式

3.1 用户级线程(User-Level Thread,ULT)

通过程序员实现的线程库来实现多线程

int main() {
    int i = 0;
    while (true) {
        if (i == 0) { 处理视频聊天的代码; }
        if (i == 1) { 处理文字聊天的代码; }
        if (i == 2) { 处理文件传输的代码; }
        i = (i + 1) % 3;   // i 的值为 0、1、2、0、1、2...
    }
}

四个问题

  1. 线程的管理工作由谁负责?

    • 用户级线程由应用程序通过线程库实现,所有的线程管理工作都由应用程序负责(包括线程切换)

  2. 线程切换是否需要 CPU 变态?

    • 用户级线程中,线程切换可以在用户态下完成,无需操作系统的干涉

  3. 操作系统是否能意识到用户级线程的存在?

    • 在用户看来,是有多个线程,但是操作系统内核看来,是意识不到线程的存在。“用户级线程”就是“从用户视角能看到的线程

  4. 这种线程的实现方式有什么优点和缺点?

    • 优点:用户级线程的切换在用户空间即可完成,不需要切换到核心态,线程管理的系统开销小,效率高

    • 缺点:当一个用户级线程被阻塞后,整个进程都会被阻塞,并发度不高。多个线程不可在多核处理机上并行运行

3.2 内核级线程(Kernel-Level Thread,KLT)

四个问题

  1. 线程的管理工作由谁负责?

    • 内核级线程的管理工作操作系统内核完成

  2. 线程切换是否需要 CPU 变态?

    • 线程调度、切换等工作都是由内核负责,因此内核级线程的切换必然需要在核心态下才能完成

  3. 操作系统是否能意识到内核级线程的存在?

    • 操作系统会为每个内核级线程建立相应的 TCB(Thread Control Block,线程控制块),通过 TCB 对线程进行管理。“内核级线程”就是“从操作系统内核视角能看到的线程

  4. 这种线程的实现方式有什么优点和缺点?

    • 优点:当一个用户级线程被阻塞后,其他线程还可以继续执行,并发度高。多个线程可在多核处理机上并行运行

    • 缺点:一个用户进程会占用多个内核级线程,线程切换由操作系统内核完成,需要切换到核心态,因此线程管理的成本高,开销大

4. 多线程模型

4.1 一对一模型

一对一模型:一个用户级线程映射到一个内核级线程。每个用户进程有与用户级线程同数量的内核级线程

优点:当一个用户级线程被阻塞后,其他线程还可以继续执行,并发度高。多个线程可在多核处理机上并行运行

缺点:一个用户进程会占用多个内核级线程,线程切换由操作系统内核完成,需要切换到核心态,因此线程管理的成本高,开销大

4.2 多对一模型

多对一模型:多个用户级线程映射到一个内核级线程。且一个进程只被分配一个内核级线程

优点:用户级线程的切换在用户空间即可完成,不需要切换到核心态,线程管理的系统开销小,效率高

缺点:当一个用户级线程被阻塞后,整个进程都会被阻塞,并发度不高。多个线程不可在多核处理机上并行运行

重点:操作系统只看得见内核级线程,因此只有内核级线程才是处理机分配的单位

4.3 多对多模型

多对多模型:n 用户级线程映射到 m 个内核级线程(n >= m)。每个用户进程对应 m 个内核级线程

克服了多对一模型并发度不高的缺点(一个阻塞全体阻塞),又克服了一对一模型中一个用户进程占用太多内核级线程,开销太大的缺点

理解:

  • 用户级线程是“代码逻辑”的载体

  • 内核级线程是“运行机会”的载体(内核级线程才是处理机分配的单位

一段“逻辑代码”只有获得了“运行机会”才能被 CPU 执行

内核级线程中可以运行任意一个有映射关系的用户级线程,只有两个内核级线程中正在运行的代码逻辑都阻塞时,这个进程才会阻塞

Last updated