细说M:N model
Publish on 2024-09-19

在仅支持进程的操作系统中,进程是拥有资源和独立调度的基本单位。在引入线程的操作系统中,线程是独立调度的基本单位,进程是资源拥有的基本单位。在同一进程中,线程的切换不会引起进程切换。在不同进程中进行线程切换,如从一个进程内的线程切换到另一个进程中的线程时,会引起进程切换

线程创建、管理、调度等采用的方式称为线程模型。线程模型一般分为以下三种:

  • 内核级线程(Kernel Level Thread)模型
  • 用户级线程(User Level Thread)模型
  • 两级线程模型,也称混合型线程模型

三大线程模型最大差异就在于用户级线程与内核调度实体KSE(KSE,Kernel Scheduling Entity)之间的对应关系。KSE是Kernel Scheduling Entity的缩写,其是可被操作系统内核调度器调度的对象实体,是操作系统内核的最小调度单元,可以简单理解为内核级线程

用户级线程即协程,由应用程序创建与管理,协程必须与内核级线程绑定之后才能执行。线程由 CPU 调度是抢占式的,协程由用户态调度是协作式的,一个协程让出 CPU 后,才执行下一个协程

用户级线程(ULT)与内核级线程(KLT)比较:

特性用户级线程内核级线程
创建者应用程序内核
操作系统是否感知存在
开销成本创建成本低,上下文切换成本低,上下文切换不需要硬件支持创建成本高,上下文切换成本高,上下文切换需要硬件支持
如果线程阻塞整个进程将被阻塞。即不能利用多处理来发挥并发优势其他线程可以继续执行,进程不会阻塞
案例Java thread, POSIX threadsWindow Solaris

内核级线程模型

ult_klt_1_1.jpg

内核级线程模型中用户线程与内核线程是一对一关系(1 : 1)线程的创建、销毁、切换工作都是由内核完成的。应用程序不参与线程的管理工作,只能调用内核级线程编程接口(应用程序创建一个新线程或撤销一个已有线程时,都会进行一个系统调用)。每个用户线程都会被绑定到一个内核线程。用户线程在其生命期内都会绑定到该内核线程。一旦用户线程终止,两个线程都将离开系统。

操作系统调度器管理、调度并分派这些线程。运行时库为每个用户级线程请求一个内核级线程。操作系统的内存管理和调度子系统必须要考虑到数量巨大的用户级线程。操作系统为每个线程创建上下文。进程的每个线程在资源可用时都可以被指派到处理器内核。

内核级线程模型有如下优点:

  • 在多处理器系统中,内核能够并行执行同一进程内的多个线程
  • 如果进程中的一个线程被阻塞,不会阻塞其他线程,是能够切换同一进程内的其他线程继续执行
  • 当一个线程阻塞时,内核根据选择可以运行另一个进程的线程,而用户空间实现的线程中,运行时系统始终运行自己进程中的线程

缺点:

  • 线程的创建与删除都需要CPU参与,成本大

用户级线程模型

ult_klt_n_1.jpg

用户线程模型中的用户线程与内核线程KSE是多对一关系(N : 1)线程的创建、销毁以及线程之间的协调、同步等工作都是在用户态完成,具体来说就是由应用程序的线程库来完成。内核对这些是无感知的,内核此时的调度都是基于进程的。线程的并发处理从宏观来看,任意时刻每个进程只能够有一个线程在运行,且只有一个处理器内核会被分配给该进程。

从上图中可以看出来:库调度器从进程的多个线程中选择一个线程,然后该线程和该进程允许的一个内核线程关联起来。内核线程将被操作系统调度器指派到处理器内核。用户级线程是一种”多对一”的线程映射

用户级线程有如下优点:

  • 创建和销毁线程、线程切换代价等线程管理的代价比内核线程少得多, 因为保存线程状态的过程和调用程序都只是本地过程
  • 线程能够利用的表空间和堆栈空间比内核级线程多

缺点:

  • 线程发生I/O或页面故障引起的阻塞时,如果调用阻塞系统调用则内核由于不知道有多线程的存在,而会阻塞整个进程从而阻塞所有线程, 因此同一进程中只能同时有一个线程在运行
  • 资源调度按照进程进行,多个处理机下,同一个进程中的线程只能在同一个处理机下分时复用

两级线程模型

ult_klt_n_m.jpg

两级线程模型中用户线程与内核线程是一对一关系(N : M)。两级线程模型充分吸收上面两种模型的优点,尽量规避缺点。其线程创建在用户空间中完成,线程的调度和同步也在应用程序中进行。一个应用程序中的多个用户级线程被绑定到一些(小于或等于用户级线程的数目)内核级线程上。

Golang的线程模型

Golang在底层实现了混合型线程模型。M即系统线程,由系统调用产生,一个M关联一个KSE,即两级线程模型中的系统线程。G为Groutine,即两级线程模型的的应用及线程。M与G的关系是N:M。

golang_ult_klt.jpg

© 2024 humbornjo :: based on 
nobloger  ::  rss