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

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

文章目录

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低级调度(进程调度)

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

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

最后的话

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

相关实践学习
CentOS 7迁移Anolis OS 7
龙蜥操作系统Anolis OS的体验。Anolis OS 7生态上和依赖管理上保持跟CentOS 7.x兼容,一键式迁移脚本centos2anolis.py。本文为您介绍如何通过AOMS迁移工具实现CentOS 7.x到Anolis OS 7的迁移。
相关文章
|
10天前
|
Linux 调度 C语言
深入理解操作系统:进程和线程的管理
【10月更文挑战第32天】本文旨在通过浅显易懂的语言和实际代码示例,带领读者探索操作系统中进程与线程的奥秘。我们将从基础知识出发,逐步深入到它们在操作系统中的实现和管理机制,最终通过实践加深对这一核心概念的理解。无论你是编程新手还是希望复习相关知识的资深开发者,这篇文章都将为你提供有价值的见解。
|
12天前
深入理解操作系统:进程与线程的管理
【10月更文挑战第30天】操作系统是计算机系统的核心,它负责管理计算机硬件资源,为应用程序提供基础服务。本文将深入探讨操作系统中进程和线程的概念、区别以及它们在资源管理中的作用。通过本文的学习,读者将能够更好地理解操作系统的工作原理,并掌握进程和线程的管理技巧。
27 2
|
14天前
|
调度 Python
深入浅出操作系统:进程与线程的奥秘
【10月更文挑战第28天】在数字世界的幕后,操作系统悄无声息地扮演着关键角色。本文将拨开迷雾,深入探讨操作系统中的两个基本概念——进程和线程。我们将通过生动的比喻和直观的解释,揭示它们之间的差异与联系,并展示如何在实际应用中灵活运用这些知识。准备好了吗?让我们开始这段揭秘之旅!
|
22天前
|
Java 开发者
在Java多线程编程中,创建线程的方法有两种:继承Thread类和实现Runnable接口
【10月更文挑战第20天】在Java多线程编程中,创建线程的方法有两种:继承Thread类和实现Runnable接口。本文揭示了这两种方式的微妙差异和潜在陷阱,帮助你更好地理解和选择适合项目需求的线程创建方式。
16 3
|
22天前
|
Java 开发者
在Java多线程编程中,选择合适的线程创建方法至关重要
【10月更文挑战第20天】在Java多线程编程中,选择合适的线程创建方法至关重要。本文通过案例分析,探讨了继承Thread类和实现Runnable接口两种方法的优缺点及适用场景,帮助开发者做出明智的选择。
15 2
|
22天前
|
Java
Java中多线程编程的基本概念和创建线程的两种主要方式:继承Thread类和实现Runnable接口
【10月更文挑战第20天】《JAVA多线程深度解析:线程的创建之路》介绍了Java中多线程编程的基本概念和创建线程的两种主要方式:继承Thread类和实现Runnable接口。文章详细讲解了每种方式的实现方法、优缺点及适用场景,帮助读者更好地理解和掌握多线程编程技术,为复杂任务的高效处理奠定基础。
28 2
|
22天前
|
Java 开发者
Java多线程初学者指南:介绍通过继承Thread类与实现Runnable接口两种方式创建线程的方法及其优缺点
【10月更文挑战第20天】Java多线程初学者指南:介绍通过继承Thread类与实现Runnable接口两种方式创建线程的方法及其优缺点,重点解析为何实现Runnable接口更具灵活性、资源共享及易于管理的优势。
28 1
|
22天前
|
安全 Java 开发者
Java多线程中的`wait()`、`notify()`和`notifyAll()`方法,探讨了它们在实现线程间通信和同步中的关键作用
本文深入解析了Java多线程中的`wait()`、`notify()`和`notifyAll()`方法,探讨了它们在实现线程间通信和同步中的关键作用。通过示例代码展示了如何正确使用这些方法,并分享了最佳实践,帮助开发者避免常见陷阱,提高多线程程序的稳定性和效率。
33 1
|
22天前
|
Java
在Java多线程编程中,`wait()` 和 `notify()/notifyAll()` 方法是线程间通信的核心机制。
在Java多线程编程中,`wait()` 和 `notify()/notifyAll()` 方法是线程间通信的核心机制。它们通过基于锁的方式,使线程在条件不满足时进入休眠状态,并在条件成立时被唤醒,从而有效解决数据一致性和同步问题。本文通过对比其他通信机制,展示了 `wait()` 和 `notify()` 的优势,并通过生产者-消费者模型的示例代码,详细说明了其使用方法和重要性。
24 1
|
18天前
|
Linux 调度
探索操作系统核心:进程与线程管理
【10月更文挑战第24天】在数字世界的心脏,操作系统扮演着至关重要的角色。它不仅是计算机硬件与软件之间的桥梁,更是管理和调度资源的大管家。本文将深入探讨操作系统的两大基石——进程与线程,揭示它们如何协同工作以确保系统运行得井井有条。通过深入浅出的解释和直观的代码示例,我们将一起解锁操作系统的管理奥秘,理解其对计算任务高效执行的影响。