线程的实现可以分为两类:用户级线程和内核级线程。

用户级线程
 

一、概述

用户级线程的实现就是把整个线程实现部分放在用户空间中,内核对线程一无所知,内核看到的就是一个单线程进程。

注:对于实现的是用户级线程的操作系统而言,CPU 调度的基本单位看起来像是进程(因为在内核看来,这些进程都是单线程的,所以对单线程的调度就像是在调度进程一样)。

二、优点

  • 整个用户级线程的切换发生在用户空间,这样的线程切换至少比陷入内核要快一个数量级(不需要陷入内核、不需要上下文切换、不需要对内存高速缓存进行刷新,这就使得线程调度非常快捷)
  • 用户级线程有比较好的可扩展性,线程能够利用的表空间和堆栈空间比内核级线程多,这是因为在内核空间中内核线程需要一些固定的表格空间和堆栈空间,如果内核线程的数量非常大,就会出现问题,因为内核空间也是很有限的。
  • 创建和销毁线程、线程切换代价等线程管理的代价比内核线程少得多, 因为保存线程状态的过程和调用程序都只是本地过程

三、缺点

  • 一个线程阻塞,会阻塞该进程中其他所有的线程。比如:线程发生 I/O 或页面故障引起的阻塞时,如果调用阻塞系统调用则内核由于不知道有多线程的存在,而会阻塞整个进程从而阻塞所有线程,缺页中断也会产生类似的问题。
  • 如果一个线程开始运行,那么该进程中其他线程就不能运行,除非第一个线程自动放弃 CPU 。因为在一个单独的进程内部,没有时钟中断,所以不能用轮转调度(轮流)的方式调度线程。
  • 还有一个缺点就是对于线程的调度方面,说是缺点是因为,不像内核线程的调度那样,由时钟中断来控制,在用户线程中我们必须自己手动编写调度的代码,这会极大的增加我们代码的复杂度。同时也是一种优点,那是因为,线程调度的控制权掌握在了我们自己手中,我可以自己定制相应的调度策略。

 
内核级线程
 

一、概述

在内核中有一个用来记录系统中所有线程的线程表(TCB,进程表PCB),当某个线程希望创建一个新线程或撤销一个已有线程时,它进行一个系统调用,这个系统调用通过对线程表的更新完成线程的创建或撤销工作。

现在主流的操作系统对于线程的实现,大多采用这种线程模型,比如 Windows、Linux 等。

二、优点

  • 当一个线程阻塞时,内核根据选择,可以运行同一个进程中的其它线程或其他进程中的线程。
  • 由内核来调(借助于时钟中断),开发者无须关心调度的实现。

三、缺点

  • 在内核中创建和撤销线程的开销比较大,速度慢

在用户级线程中,有关线程管理的所有工作都由应用程序完成,内核意识不到线程的存在。应用程序可以通过使用线程库设计成多线程程序。

在内核级线程中,线程管理的所有工作都由内核完成,应用程序没有进行线程管理的代码,只有一个到内核级线程的编程接口。内核为进程及内部的每个线程维护上下文信息,调度也在内核基于线程架构的基础上完成。

 

用户线程与内核线程的对比
 

关于用户级线程和内核级线程这两种线程模型的对比,个人认为主要可以从调度、开销、性能这三个角度来看待。

  • 调度:对于用户级线程,操作系统内核不可感知,调度需要由开发者自己实现,内核级线程则与之相反,开发者可以做个甩手掌柜,将调度全权交由操作系统内核来完成。
  • 开销:在前面介绍用户级线程的优点时,也提到了,在用户空间创建线程的开销相比之下会比内核空间小很多。
  • 性能:用户级线程的切换发生在用户空间,这样的线程切换至少比陷入内核要快一个数量级,不需要陷入内核、不需要上下文切换、不需要对内存高速缓存进行刷新,这就使得线程调度非常快捷。

 

  • 区别
  • 内核级线程:

(1)线程的创建、撤销和切换等,都需要内核直接实现,即内核了解每一个作为可调度实体的线程。
(2)这些线程可以在全系统内进行资源的竞争
(3)内核空间内为每一个内核支持线程设置了一个线程控制块(TCB),内核根据该控制块,感知线程的存在,并进行控制
在一定程度上类似于进程,只是创建、调度的开销要比进程小。有的统计是1:10

 

用户级线程:

(1)用户级线程仅存在于用户空间。
(2)内核并不能看到用户线程。
(3)内核资源的分配仍然是按照进程进行分配的;各个用户线程只能在进程内进行资源竞争

引入用户线程,具体而言,有以下四个方面的优势:

(1)       可以在不支持线程的操作系统中实现。

(2)       创建和销毁线程、线程切换代价等线程管理的代价比内核线程少得多。

(3)       允许每个进程定制自己的调度算法,线程管理比较灵活。

(4)       线程能够利用的表空间和堆栈空间比内核级线程多。

  • 多线程模型:

支持多线程的操作系统中一般采用三种调度模型,分别是“一对一模型”、“多对一模型”、“多对多模型”。

1、多对一模型

将多个用户级线程映射到一个内核级线程,线程管理在用户空间完成。用户级线程对操作系统不可见(透明)。

优点:线程管理是在用户空间进行的,因而效率比较高

缺点:一个线程在使用内核服务时被阻塞,整个进程都会被阻塞。

2、一对一模型

将每个用户级线程映射到一个内核级线程。

优点:当一个线程被阻塞时,允许另一个线程继续运行,并发能力强。

缺点:每创建一个用户级线程都需要创建一个内核级线程与其对应,这样创建线程的开销比较大,会影响到应用程序的性能。

3、多对多模型

将n个用户级线程映射到m个内核级线程上,要求m<=n;

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐