线程

引例

比如我们要编写一个看的视频软件。要实现的功能有:

  • 从视频文件中读取数据。
  • 对读取的数据解压缩。
  • 把解压缩后的视频播放出来。

对于单进程的程序而言,会有如下实现方式:

但是这个方法存在问题:

  • 播放出来的视频和声音会不连贯,因为当CPU计算能力不够强的时候,Read进程就可能阻塞了,这样需要等半天才能将数据解压,播放。
  • 各线程直接不能并发进行,影响资源利用率。

对于多进程的程序而言,会有如下实现方式:

但是这个方法仍然存在问题:

  • 进程之间应该如何通信?
  • 系统维护进程的开销比较大,如创建进程时需要分配资源,初始化PCB。终止进程时需要释放资源,删除PCB。

那到底如何解决呢?我们需要一种新的实体,这个实体满足:

  • 实体之间共享数据和资源。
  • 实体之间可以并发运行。

这个新的实体就是线程,线程直接可以并发执行。

什么是线程,为什么要引入线程?

线程是一个基本的CPU执行单元,也是程序执行流的最小单位。引入线程之后,不仅是进程之间可以并发,进程内的各线程之间也可以并发,从而进一步提升了系统的并发度,使得一个进程内也可以并发处理各种任务。(如QQ视频。文字聊天,传文件)

alt text

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

引入线程机制后,有什么变化?

  • 资源分配、调度
    • 传统进程机制中,进程是资源分配、调度的基本单位。
    • 引入线程后,进程是资源分配的基本单位,线程是调度的基本单位。
  • 并发性
    • 传统进程机制中,只能进程间并发
    • 引入线程后,各线程间也能并发,提升了并发度。
  • 系统开销
    • 传统的进程间并发,需要切换进程的运行环境,系统开销不是很大
    • 线程间并发,如果是同一个进程内的线程切换,则不需要切换进程环境,系统开销小。
    • 引入线程后,并发所带来的系统开销小。

线程特点

  1. 线程是处理机调度的单位。
  2. 多CPU计算机中,各个进行可占用不同的CPU
  3. 每个线程多有一个线程ID、线程控制块(TCB)
  4. 线程也有就绪,阻塞,运行三种基本状态。
  5. 线程几乎不拥有系统资源。
  6. 同一进程的不同线程间共享数据资源。
  7. 由于共享内存地址空间,同一进程中的线程间通信甚至无需系统干预
  8. 同一进程中的线程切换,不会引起进程切换。
  9. 不同进程中的线程切换,会引起进程切换。
  10. 切换同进程内的线程,系统开销很小。
  11. 切换进程,系统开销很大。

多线程模型

一对一模型

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

alt text

优点:当一个线程被阻塞后,别的线程还可以继续执行,并发能力强。多线程可以在多核处理机上并行执行。

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

多对一模型

多个用户级线程映射到一个内核级线程,且一个线程只被分配一个内核级线程。

alt text

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

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

多对多模型

多对多模型:n用户级及线程映射到m个内核级线程(n >= m)。每个用户进程对应m个内核级线程。克服了一对一模型线程调度消耗大和多对一模型并发度不高的缺点。

alt text

线程的实现

用户级线程

早期的操作系统只支持进程,不支持线程。当时的线程是由线程库实现的。

alt text

  1. 用户级线程应由应用程序通过线程库实现,所有的线程管理工作都由应用程序负责(包括线程切换)
  2. 用户级线程中,线程切换可以在用户态下即可完成,无需操作系统干预。
  3. 在用户看来,是有多个线程。但是在操作系统内核看来,并意识不到线程的存在。用户级线程就是从用户视角能看到的线程。

优点:

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

缺点:

  • 当一个用户级线程被阻塞后,这个进程就会被阻塞,并发度不高。多个线程不能再多核处理机上运行。

内核级线程

alt text

线程的管理工作由谁来完成?

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

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

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

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

操作系统会为每个内核级进程建立相应的TCB,通过TCB对线程进行管理。内核级线程就是从操作系统内核视角能看的线程。

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

优点:

  • 当一个线程被阻塞后,别的线程还可以继续执行,并发能力强。多线程可在多核处理机上运行。

缺点:

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

总结

  • 用户级线程是代码逻辑的载体。
  • 内核级线程是运行机会的载体。
  • 内核级线程是处理调度的基本单位。只有内核级线程被CPU执行,内核级线程所映射的用户级线程在会被执行。只有两个内核级线程中正在运行的代码逻辑都被阻塞是,这个进程才会被阻塞。

线程的状态与转换

alt text

  1. 线程创建之后由创建态变为就绪态。
  2. 线程如果被调度程序选中,就会上处理运行,线程由就绪态变为运行态。
    1. 如果线程在运行过程中需要等待IO事件发生,线程会由运行态变为阻塞态,下处理机。如果IO事件发生,线程会由阻塞态变为就绪态,等待被调度程序选中。
    2. 如果线程的时间片用完,线程会由运行态变为就绪态,下处理机。

线程的组织和控制

alt text