挑战408——操作系统(6)——线程详解

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/redRnt/article/details/83144696

20世纪80年代,人们提出了比进程更小,并能独立运行的基本单位——线程。如果说进程的目的是为了让多个程序彼此之间能够并发执行,那么引入线程就是为了减少并发执行所付出的时间和空间开销。从而使得操作系统具有更好的并发性。

线程的作用

由于进程是一个资源的拥有者,因此在进程的创建,撤销以及状态转换中都要付出巨大的时间和空间开销。因此系统中的进程都不宜过多(打开你们的任务管理器,运行的进程都能数出来),因为我们的主存空间是有限的。但这样就很明显的限制了并发程度的提高,因为可以运行的道数少了。
先回顾一下进程的两个基本属性

  1. 能拥有资源
  2. 可以独立调度和分派的单位

若把这两个属性分开,那么进程不再作为调度和分派的单位,将这一功能交给其他单位去完成,这个单位就是线程。线程是进程的一个实体同一个进程内可以访问进程内部的所有资源(但不包括指向下一个进程的栈指针,因为它对线程透明)。而且线程中的通信比进程中的通信方便的多。
在这里插入图片描述
假设用方框表示进程,曲线表示线程,那么上面的三个图分别表示,单进程单线程,单进程多线程,多进程多线程。

线程与进程之间的区别与联系

类似于进程,每个进程都有一个线程控制块(TCB),用于保存自己私有信息。而且线程的状态,及其控制跟进程一样。但是尽管如此相似,但是还是有所区别的。

  1. 一个进程至少拥有一个线程,进程可以根据需要创建其他进程,也可以创建若干个线程。而线程虽然可以创建其他线程,但是不能创建进程。
  2. 进程是个拥有资源的独立单位,而线程本身基本不拥有资源(只含有必不可少的资源,比如TCB和栈)。
  3. 在通信方面进程中所有的线程共享该进程的所有资源在通信方面进程中所有的线程共享该进程的所有资源,并驻留在同一地址空间,访问相同的数据。但是进程只能通过同步,互斥来实现对共享资源的访问
  4. 从调度的角度,在引入线程的操作系统中,线程是调度和分派的基本单位,进程是资源分配的基本单位。在同一个进程中,线程的切换不会引起进程的切换,只有在进程中一个线程切换到另一个进程的线程中的时候,才会引起进程的切换。
  5. 从系统开销来说。在创建和撤销进程的时候,操作系统所付出的时间和空间开销将远远大于重建或者撤销线程的开销

线程的实现

我们知道,对于进程而言,无论是系统进程还是用户进程,只要涉及进程的切换,在切换过程中都要依赖内核的进程调度程序。但是在线程中,这就不一定了。我们将线程的实现分为用户级线程内核级线程

用户级线程

下图表示用户级线程的实现方式:
在这里插入图片描述
在纯粹实现用户级线程的软件中,有关线程管理的所有工作都由应用程序完成,应用程序和它所有的线程被分配到一个由内核管理的进程中,对于用户级进程,一个进程内线程的行为不会影响其他进程,内核只是对进程进行适当的调度。

内核级线程

在这里插入图片描述
在仅有内核级线程的操作系统中,有关线程管理的所有工作都由内核完成,应用程序要想使用线程,只有通过内核提供的API系统的调度是基于线程的,也就是说,处理机的切换是以线程为单位进行的(所以线程是可以独立运行的)。事实上,在内核级系统中,进程是资源的拥有者,线程是作为调度的基本单位,每个进程至少有一个线程。

两者的区别

  1. 从切换速度来看,显然用户级线程的速度快,因为它不需要进入操作系统内核
  2. 当某一线程,用户级线程阻塞,那么对应的内核级线程也阻塞,其他可以并发执行的线程也必须阻塞(因为他们不能进入内核的那个进程中)。但是内核级线程却不受此影响。

多线程的问题

问题一: 如何对多个线程进行取消?
答:多个线程执行同一个任务,其中一个线程任务完成,那么剩余的进程就应该取消(比如多个线程查找某个文件或者数字)。线程的取消是指在完成任务之前终止,分为立即取消和延迟取消两种
问题二:如果每一个请求,便创建一个线程,那么请求过多的时候,有限的系统资源就会被耗尽,那么如何解决这一问题?
答:可以采用线程池的思想解决:

  1. 进程一开始时,创建一定量的线程,放入池中等待
  2. 收到请求后,唤醒其中的一个线程,并将要处理的请求传递给它。
  3. 线程完成任务返回池中等待
  4. 若没有可用线程,那么服务器等待,直到出现空闲线程为止

(学过数据库的同学应该知道,连接池的思想正是如此)

多线程模型

多线程模型是即实现用户级线程,又实现内核级线程的一种连接方式。(0因此该模型一定同时支持用户级线程和内核级线程)。也称组合方式
在这里插入图片描述
(1) 多对一模型:这个模型实际上就是用户级模型,多个用户级映射到一个内核级线程,用户级线程对操作系统是透明的。(也就是说当某个线程阻塞了,内核只是知道阻塞了,却不清楚具体的情况。它只是负责调用)。显然它存在一个线程阻塞,其他线程都阻塞的风险。
(2)一对一模型:将每个用户级线程映射到一个内核级线程。这样虽然确保了进程之间不会相互影响,但是创建的线程开销很大。
(3)多对多模型:将n个用户映射到m个内核级线程上(m<=n)

猜你喜欢

转载自blog.csdn.net/redRnt/article/details/83144696