《计算机操作系统-第五章》之线程与多线程模型

简介: 《计算机操作系统-第五章》之线程与多线程模型

文章目录

1.线程

为什么需要线程?

2.什么是线程?

2.1引入线程后的变化

2.2线程的属性

2.3线程的实现方式

2.3.1用户级线程

2.3.2内核级线程

2.3.3内核级线程与用户级线程同在

3.多线程模型

3.1多对一模型

3.2一对一模型

3.3多对多模型

4.处理机调度

4.1高级调度(作业调度)

4.4中级调度(内存调度)

4.5低级调度(进程调度)

1.线程

为什么需要线程?

在很久很久以前,系统中各个程序只能串行执行,也就是qq音乐和qq没法同时运行。后来引入进程,qq和qq音乐就可以并发的执行了。但是这里有个问题,比如qq不仅可以同时文字聊天还可以视频聊天,而我们又知道进程是程序的一次执行,这些功能显然是不可能有一个程序的顺序,如果是按照顺序执行,那么qq就无法做到能同时完成多个功能。因此就引入了线程,来增加并发度。

引入线程前,传统的进程就是执行流的最小单位,假设内存中存在两个进程,分别为进程1和进程2,那么CPU就要被这两个进程并发使用。当引入线程后进程里面可以拥有对个线程,那么CPU就是给进程中的线程并发执行。这样就可以达到qq既可以文字聊天也可以视频聊天。

2.什么是线程?

可以把线程理解为轻量级的进程,线程的创建和回收所消耗的资源远远小于进程的创建和销毁。有了线程后,线程就成了CPU一个基本的执行单元,即程序流的最小单位。

注意

1.引入线程后,进程只作为除CPU之外的系统资源的分配单位(如内存空间)

2.引入线程后,不仅仅是进程之间可以并发,进程内的各线程之间也就可以并发,从而提高了并发度,使得一个进程内也可以处理各种任务

2.1引入线程后的变化

从资源分配,调度的角度来看

  1. 1.传统进程机制中,进程是资源分配,调度的基本单位
  2. 2.引入进程后,进程是资源分配的基本单位,线程是调度的基本单位

从并发性来看

  1. 1.传统进程机制中,只能进程间并发
  2. 2.引入线程后,各线程间也能并发,提高了并发度

从系统开销角度来看

  1. 1.传统的进程间并发,需要切换进程的运行环境,系统开销大
  2. 2.线程间并发,如果是同一个进程内的线程切换,则不需要切换进程环境,系统开销小
  3. 3.引入线程后,并发所带来的系统开销小。

2.2线程的属性

  1. 1.每个线程都有一个线程ID,线程控制块(TCB)
  2. 2.线程几乎不拥有系统资源
  1. 3.同一进程的不同线程间共享进程的资源
  2. 4.由于共享内存地址空间,同一进程中的线程间通信甚至需要系统干预
  3. 5.不同进程中的线程切换,会引起进程切换
  4. 6.多核CPU,各个线程可占用不同的CPU

2.3线程的实现方式

2.3.1用户级线程

用户级线程由应用程序通过线程库是实现。所有的线程管理工作都由应用程序负责(包括线程切换)。用户级线程中,线程切换可以在用户态下即可完成,无需操作系统干预。在用户看来,是有多个线程.但是在操作系统内核看来,并没有意识到线程的存在,而是意识到进程的存在,因此调度的基本单位为进程。

如图所示

2.3.2内核级线程

内核级线程的管理工作由操作系统内核完成。线程调度,切换等工作都由内核完成,因此内核级线程的切换必然需要在核心态下才能完成。从内核角度来看内存中有三个线程,一个进程。

如图所示

2.3.3内核级线程与用户级线程同在

两者结合,也就是将n个用户级线程映射到m个内核级线程上(n>=m)

如图所示

操作系统看的见内核级线程,因此只有内核级线程才是处理机分配的单位。举个栗子,上图中该进程有2个内核级线程,三个用户级线程,站在用户角度有三个线程。当该进程处于多核CPU的计算机上运行时,也最多只能分配2个CPU核心,最多只有2个用户级线程运行 。

3.多线程模型

在同时支持用户级线程和内核级线程的系统中,由几个用户级线程映射到几个内核级线程的问题引出了多线程模型问题

3.1多对一模型

多个用户级线程映射到一个内核级线程。每个用户进程只对应一个内核级线程。

如图所示

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

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

3.2一对一模型

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

如图所示

优点

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

缺点

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

3.3多对多模型

n个用户级线程映射到m个内核级线程。每个用户级进程对应m个内核级线程。

如图所示

该模型其前两种模型的优点,克服了多对一模型并发度不高的缺点,又克服了一对一模型中一个用户进程占用太多内核级线程,开销太大的缺点。

4.处理机调度

现实世界里,当一群人去银行办事,普通用户则是按时间顺序排好队依次进入银行,而VIP客户则可以优先被服务。在计算机世界里,当有一堆任务要处理,但是由于资源有限(银行),这些事没办法同时处理.这就需要确定某种规则(VIP/时间顺序)来决定处理任务的顺序,这就是调度研究的问题。

在多道程序系统中,进程的数量是远远大于处理机(CPU)的数量,这样不可能同时并发的执行的处理各个进程。处理机调度,就是从就绪队列中按照一定的算法选择一个进程并将处理机分配给它运行,以实现进程的并发执行。

4.1高级调度(作业调度)

由于内存空间有限,有时无法将用户提交的作业全部放入内存中,因此就需要确定某种规则来决定将作业调入内存的顺序。

高级调度:按照一定的原则从外存上处于后备队列的作业中挑选一个(或多个)作业,给他们分配内存等必要资源,并建立相应的进程(建立PCB),以使它获得竞争处理机的权利。

高级调度是外存与内存之间的调度。每个作业只调入一次,调出一次。作业调入时会建立相应的PCB,作业调出时才撤销PCB。高级调度主要是指调入的问题,因为只有调入的时机需要操作系统来确定,但调出的时机必然是作业运行结束才调出。

4.4中级调度(内存调度)

引入虚拟存储技术之后,可将暂时不能运行的进程调至外存等待。等它重新具备了

运行条件且内存又稍有空闲时,再重新调入内存。这样做的目的就是为了提高内存利用率和系统吞吐量。

暂时调到外存等待的进程状态为挂起转态。注意,PCB并不发一起调度到外存,而是会常驻内存.PCB中会记录进程数据在外存中的存放位置,进程转态等信息,

中级调度:就是要决定将那个处于挂起转态的进程中重新调入内存。一个进程可能会被多次调出,调入内存,因此中级调度发生的频率要比高级频率度更高。

七状态模型

暂时调到外存等待的进程状态为挂起状态(挂起态)

挂起态又可以分为就绪挂起,阻塞挂起两种状态

如图所示

注意挂起和阻塞的区别,两种状态都是暂时不能获得CPU的服务,但挂起状态是将进程映像调到外存去了,而阻塞态进程映像还在内幕内存中。

4.5低级调度(进程调度)

其主要任务是按照某种方法从就绪队列中选取一个进程,将处理机分配给它。

进程调度是进程并发执行的基础,是操作系统中最基本的一种调度。进程的调度的频率很高,一般几十毫一次。

最后的话

各位看官如果觉得文章写得不错,点赞评论关注走一波!谢谢啦!。如果你想变强那么点我点我 牛客网

相关文章
|
3月前
|
安全 算法 Java
Java 多线程:线程安全与同步控制的深度解析
本文介绍了 Java 多线程开发的关键技术,涵盖线程的创建与启动、线程安全问题及其解决方案,包括 synchronized 关键字、原子类和线程间通信机制。通过示例代码讲解了多线程编程中的常见问题与优化方法,帮助开发者提升程序性能与稳定性。
142 0
|
8月前
|
存储 Linux API
【Linux进程概念】—— 操作系统中的“生命体”,计算机里的“多线程”
在计算机系统的底层架构中,操作系统肩负着资源管理与任务调度的重任。当我们启动各类应用程序时,其背后复杂的运作机制便悄然展开。程序,作为静态的指令集合,如何在系统中实现动态执行?本文带你一探究竟!
【Linux进程概念】—— 操作系统中的“生命体”,计算机里的“多线程”
|
3月前
|
Android开发 Windows
这是我设想的免重启操作系统的状态下更新通用计算机、嵌入式操作系统的软件设计思路
本方案提出了一种名为slfm的软件系统,旨在实现通用计算机及嵌入式系统在不重启状态下完成操作系统更新。其核心机制是通过构建独立于原系统的运行环境(slfm Recovery与The Tube),在高权限模式下进行系统文件更新与切换,确保更新过程中设备持续运行,适用于普通设备与不可中断服务的关键系统(如医疗、服务器等)。同时具备失败回滚、数据同步、权限隔离等功能,提升系统更新的安全性与可用性。
|
3月前
|
数据采集 监控 调度
干货分享“用 多线程 爬取数据”:单线程 + 协程的效率反超 3 倍,这才是 Python 异步的正确打开方式
在 Python 爬虫中,多线程因 GIL 和切换开销效率低下,而协程通过用户态调度实现高并发,大幅提升爬取效率。本文详解协程原理、实战对比多线程性能,并提供最佳实践,助你掌握异步爬虫核心技术。
|
4月前
|
Java 数据挖掘 调度
Java 多线程创建零基础入门新手指南:从零开始全面学习多线程创建方法
本文从零基础角度出发,深入浅出地讲解Java多线程的创建方式。内容涵盖继承`Thread`类、实现`Runnable`接口、使用`Callable`和`Future`接口以及线程池的创建与管理等核心知识点。通过代码示例与应用场景分析,帮助读者理解每种方式的特点及适用场景,理论结合实践,轻松掌握Java多线程编程 essentials。
248 5
|
5月前
|
安全 Java 调度
Netty源码—3.Reactor线程模型二
本文主要介绍了NioEventLoop的执行总体框架、Reactor线程执行一次事件轮询、Reactor线程处理产生IO事件的Channel、Reactor线程处理任务队列之添加任务、Reactor线程处理任务队列之执行任务、NioEventLoop总结。
|
5月前
|
安全 Java
Netty源码—2.Reactor线程模型一
本文主要介绍了关于NioEventLoop的问题整理、理解Reactor线程模型主要分三部分、NioEventLoop的创建和NioEventLoop的启动。
|
7月前
|
缓存 NoSQL 中间件
Redis的线程模型
Redis采用单线程模型确保操作的原子性,每次只执行一个操作,避免并发冲突。它通过MULTI/EXEC事务机制、Lua脚本和复合指令(如MSET、GETSET等)保证多个操作要么全成功,要么全失败,确保数据一致性。Redis事务在EXEC前失败则不执行任何操作,EXEC后失败不影响其他操作。Pipeline虽高效但不具备原子性,适合非热点时段的数据调整。Redis 7引入Function功能,支持函数复用,简化复杂业务逻辑。总结来说,Redis的单线程模型简单高效,适用于高并发场景,但仍需合理选择指令执行方式以发挥其性能优势。
176 6
|
8月前
|
Python
python3多线程中使用线程睡眠
本文详细介绍了Python3多线程编程中使用线程睡眠的基本方法和应用场景。通过 `time.sleep()`函数,可以使线程暂停执行一段指定的时间,从而控制线程的执行节奏。通过实际示例演示了如何在多线程中使用线程睡眠来实现计数器和下载器功能。希望本文能帮助您更好地理解和应用Python多线程编程,提高程序的并发能力和执行效率。
258 20

推荐镜像

更多