CHS_06.2.1.6_2+线程的实现方式和多线程模型

news2024/11/20 11:45:56

CHS_06.2.1.6_2+线程的实现方式和多线程模型

  • 知识总览
  • 线程的实现方式
    • 用户级线程(User-Level Thread, ULT)
    • 内核级线程
  • 多线程模型
    • 一对一模型
    • 多对一
    • 多对多模型
  • 知识回顾

在上个小节中 我们学习了线程相关的一些基本概念 基础的知识

那这个小节中 我们回来看一下有哪几种线程的实现方式 并且会学习几种多线程模型

知识总览

在这里插入图片描述

那线程的实现方式分为用户及线程和内核及线程 另外 还有的系统当中会把这两种实现方式都混合起来使用

线程的实现方式

那这个大家一会会看到实际的例子 那首先我们来看一下 第一种线程的实现方式叫做用户级线程

用户级线程(User-Level Thread, ULT)

在这里插入图片描述

其实这种实现方式是在早期的操作系统 也就是只支持进程 还暂时没有支持线程的那些操作系统当中

来使用的 当时所谓的线程是由程序员们写的线程库来实现的

也就是说 在这个时代 操作系统的视角看到的其实依然是只有进程

但是程序员们写的这些应用程序当中 可以使用线程库来实现多个线程并发的运行这样的事情

我们还是来结合上小节当中提到的这个例子来进行理解 上个小节中我们提到过

我们的qq可以一边视频聊天一边文字聊天 一边实现文件传输 那上个小节中我们提出了这样的方案

如果要让这三个事情并发的运行的话 那么在不支持线程的系统当中 我们可以分别建立三个进程 这三个进程分别是处理其中的某一个事情

进程一的代码是不断不断的来处理视频聊天这个事情 进程二是不断不断的来处理这个文字聊天 而进程三是处理这个文件传输

那我们可以看到 处理视频聊天的这个代码是在是用这个循环来一遍一遍一遍的不断的执行的

另外的两个代码也一样 所以其实我们可以用这样的方式来实现 让这三段代码并发的运行

我们用一个循环 让它一直不断的循环 然后这个 i 的值会012012这样循环的变化
在这里插入图片描述

当 i 等于零的时候 我们可以让这个进程来处理视频聊天

当 i 等于一的时候 让他处理文字聊天 当 i 等于二的时候让他处理文件传输

那由于我们这个程序 进行y循环的速度是非常快的 那我们其实也可以把这三段代码

看作是三段并发的运行的代码 他们分别处理了不同的事情 所以其实如果我们从单纯代码的角度来看的话

那么一个线程 其实我们可以把它理解为是一段代码逻辑 那这个地方提到的这三段代码逻辑 我们就可以把它看作是三个线程 另外 我们这儿写的循环的这个处理逻辑 其实我们就可以把它看成一个最简陋 最弱智的一个线程库

这个线程库完成了对各个线程的一个管理调度的工作 那这个落那 这个弱质线程库对我们的这些线程的调度规则很简单

就是第一次先处理视频 第二次处理文字 第三次处理文件 第四次又处理视频 第五次处理文字等等等等

这个地方 我们用一个简单的while循环和几个if语句就实现了一个最简单最简单最简单的线程库

那我们很多的编程语言都会提供用于管理线程的线程库
在这里插入图片描述

不过他们提供的线程库要比我们的外循环复杂多了 程序员可以利用这个线程库来实现这个用户及线程的创建 销毁 调度等等一系列的功能

那接下来 问题来了 在刚才我们所说的这个例子当中 操作系统其实他只看得到进程

而这个进程上处理机运行的时候 其实是程序员自己写了一个线程库来创建了逻辑上的线程

也就是这所谓的用户及线程 那我们来思考这样的几个问题 第一这些用户及线程的管理工作是由谁来完成的

其实我们刚才写的这个while循环就是简单的实现了对这三个线程的管理 让他们交替的运行

所以 用户级线程的管理工作是由应用程序通过线程库来完成的
并不是操作系统负责的
第二个问题 线程切换是否需要cpu
从用户态转换为内核态 那经过刚才的分析 这个问题其实也不难回答
我们的线程切换其实是由我们这个循环来控制的 这并不需要涉及到请求操作系统服务之类的事情

所以 线程切换的管理是由我们的线程库应用程序自己完成的

在用户态下就可以完成线程的切换工作 并不需要操作系统的干涉

第三个问题 操作系统是否能意识到用户级线程的存在 那显然操作系统他只能看到这个进程的存在
在这里插入图片描述

他只知道这个进程 它是一坨代码 而在这坨代码里面又分别被分为了几个线程 操作系统是意识不到这些线程的存在了

所以 这也是为什么这种线程的实现方式叫做用户及线程的原因

只有用户才能感知到这个用户及现成的存在 而操作系统其实感知不到这些用户及现成的存在

那最后我们要思考的问题是 这种实现方式 它有什么优点和缺点呢

首先来看优点 刚才我们提到过用户级线程的管理工作 包括切换 创建等等 这些工作都不需要请求操作系统的服务 只需要在用户态下就可以完成

也就是说 对用户级线程的管理并不需要涉及到cpu变态这个事情

而之前我们说过cpu变态是有开销 有成本的 所以那既然用户及线程的管理工作不需要cpu切换到内核态 所以对于他们的管理工作 肯定开销是比较小 效率是比较高的

那接下来来看一下用户级线程 这种实现方式有什么缺点 那我们回到我们自己实现的这三个最简单的用户级线程

我们来看一下 假设此时这个qq进程上处理机运行 而这次运行的时候

i 的值是等于零的 也就说视频聊天的这一段代码会上处理机运行

但是 假设视频聊天的这段代码在运行的过程中发生了阻塞

比如说 他想要申请摄像头那个资源 但是申请失败 那么由于他想要的这个系统资源得不到满足 因此这段代码的执行就会被阻塞

那我们想一下 既然这个代码的执行被阻塞在了这个地方 那么这个while循环还能继续下去吗

肯定不行了 对吧 只有这个阻塞被解除之后 这个循环才可以继续执行下去

所以 这种用户级线程的实现方式有一个很明显的缺点 那就是

如果其中的某一个线程被阻塞 那么其他的这些线程也会被阻塞 也没办法执行下去

那从这段伪代码当中 相信不难理解这一点 所以这就是用户级线程这种实现方式最大的一个缺点
只要其中一个被阻塞 那整个进程都会被阻塞 所以这种方式的并发度并不高

另外 虽然上个小节中我们提到过 引入线程之后 线程成为了cpu调度的基本单位
但是 如果这个线程是用用户籍线程这样的方式来实现的话 那么在这种情况下 其实cpu的调度单位依然是进程

操作系统是给进程分配cpu时间的 因此即便我们的电脑是多核处理机

但是 由于进程才是cpu调度的基本单位 因此这个进程只能被分配一个核心

所以 这些线程并不能并行的运行 那这是早期的操作系统当中人们实现线程的方式

在这个阶段 操作系统还只支持进程 并不支持线程 那之后随着操作系统的发展

越来越多操作系统开始支持线程 那操作系统支持的这种线程就叫做内核级线程

内核级线程

在这里插入图片描述

那这种内核及线程就是操作系统视角也可以看得到了线程 那现代的操作系统大多都支持内核级线程 比如说我们很熟悉的windows linux等等

那接下来我们还是要思考同样的三个问题 在引入了内核及线程之后 这个线程的管理工作到底是谁来做呢

那由于这个内核及线程是在操作系统层面实现的线程 因此这个内核级线程的管理工作当然是需要由操作系统来完成

第二个问题 线程的切换是否需要cpu状态的转换 那既然这些内核及线程由操作系统负责管理

那他们的切换 他们的管理工作肯定是需要操作系统介入的 因此在进行线程切换的时候 当然是需要从用户态转变为内核态

第三个问题 操作系统是否能够意识到内核级线程的存在 这个不用说了 最后我们根据刚才认知道的这些信息来分析一下

这种实现方式有什么优点和缺点 首先来看优点 如果某一个操作系统 它支持内核及线程的话

那么 在这种操作系统当中 内核级线程 它是处理机调度的基本单位

而进程只作为分配资源的基本单位 因此在多核cpu的环境下

这几个线程可以分别分配到不同的核心下并行的执行 另外呢 不同的内核及线程中可以跑不同的代码逻辑

比如说这个代码逻辑是实现视频聊天 这个是实现文字聊天 这个是实现文件传输 那么 由于内核及线程 它是处理及分配的基本单位 那在这种情况下 即便其中的某一个线程被阻塞 那其他的两个线程依然可以继续执行下去

所以采用这种方式有一个优点 那就是线程之间的并发能力强 那再来看一下这种方式的缺点

当引入了内核级线程之后 那一个进程有可能会对应多个内核级线程

那操作系统需要对这些线程进行管理 所以内核及线程之间的切换是需要cpu从用户台变为内核态的

当切换完成之后 还需要从内核态转回用户态 而之前我们提到过很多次cpu变态 是有成本有开销的
所以这种实现方式会导致现成的管理成本要更高 开销更大
那刚才我们学习了用户级线程和内核级线程这两种线程的实现方式

那这两种方式都有各自的优点和缺点 那有没有可能把这两种方式结合起来呢

那在支持内核级线程的系统当中 如果在引入线程库的话 那么我们就可以实现把若干个用户及线程应设到某一个内核级线程这样的事情

多线程模型

在这里插入图片描述

那根据用户级线程和内核级线程的这种映射关系 就引出了三种多线程模型

像刚才我们一直在讲的这种模型 一个用户及线程对应一个内核及线程 这个是一对一模型

一对一模型

在这里插入图片描述

那如果采用这种映射方式的话 一个进程 它有多少个用户级线程 就会有多少个内核级线程 它们都是一对应的

那这种方式的优点呢 就是刚才我们提到过的 一个线程被阻塞之后 别的线程还可以继续执行 因为内核级线程是处理及分配的基本单位

另外 这些代码逻辑 这些线程可以分配到多核处理机上并行的执行 这是它的优点

而缺点呢 和刚才我们所说的一样 就是管理的成本高 开销大 因为线程的管理工作肯定需要切换到内核态

那只要涉及到cpu变态 就会使开销变大 那再来看
第二种多线程模型 叫做多对一

多对一

在这里插入图片描述

也就是多个用户级线程映射到一个内核级线程 那如果是这种映射关系的话 其实它就退化成了我们之前提到的

纯粹的用户级线程那种实现方式 那由于一个进程只被分配到了一个内核机的线程

而在这个内核级线程上面 通过线程库又实现了三个用户级的线程 因此这些线程的管理工作只需要在用户态下就可以完成

所以线程的管理开销小 效率高 但是缺点呢就是其中的一个用户级线程阻塞之后 会导致其他的用户级线程也跟着被阻塞 并发性不高

并且 这些用户级线程是不可能并行的运行的 因为只有内核级线程才是处理机的分配单位 如果一个进程 它只对应一个内核级线程的话

那么 在同一时刻 这个进程肯定只能被分配一个cpu的核心 当然如果给这个进程分配多个内核级线程的话

那么在多核cpu环境下 这些内核级线程肯定是可以并行的运行的 不过在我们的考试当中

如果提到这种多对一的线程模型的话 那么我们默认一个进程只被分配了一个内科技的线程

那最后 我们要认识的是多对多模型 就是把n个用户级线程映射到m个内核级线程上

多对多模型

在这里插入图片描述

n的数量要大于等于m 那在这个模型当中 由于一个进程 它有两个内核级线程

因此 其中一个内核级线程被阻塞的话 另一个内核级线程是可以继续运行下去的 因此它克服了多对一模型并发度不高的缺点
另方面 这种多对多的模型n是大于等于m的 也就是说内核级线程的数量它要比用户级线程的数量要更小
因此 操作系统对这些线程的管理开销也相应的会更小 而在一对一模型当中 有多少个用户极限程就需要给他创建多少个对应的内核级线程

那内核级线程太多的话 操作系统的管理开销就会更大 所以这种方式他又克服了一对一模型当中

线程管理开销太大的一个缺点 那我们再来总结一下用户级线程和内核级线程的

知识回顾

在这里插入图片描述

一个区别和联系 我们可以这么难理解所谓用户级线程

我们可以把它理解为是一个代码逻辑的载体 比如说这个用户及现成

它承载的是文字聊天相关的代码逻辑 这个用户及现成它承载的是文件传输相关的代码逻辑

而内核级线程可以理解为是运行机会的一个载体 因为操作系统在分配处理机cpu资源的时候

是以内核级线程为单位进行分配的 所以在这边这个模型当中虽然有三个用户级线程

但是啊 这个进程最多只可能被分配两个cpu的核心

我们的一段代码逻辑只有获得了运行机会的时候 他才可以被cpu执行

那这可以让我们的线程管理有更多的灵活性 比如说在这边这个例子当中 如果我们的qq视频聊天需要耗费比较多的cpu资源的话

那么我们可以让左边这个内核级线程 让他专门来执行视频聊天相关的

这个代码逻辑 而右边这个内核级线程 我们可以让它并发的执行文件传输和文字聊天这两个部分的逻辑

那如果某一个时刻文件传输又要耗费很多的cpu资源的话 那么我们可以把文字聊天这块的逻辑把它映射到这边 让这个内核级线程来进行处理

那需要注意的是 在引入了内核级线程之后 一个进程可能会对应多个内核级线程

而只有所有的这些内核机线程都被阻塞的时候 我们才说这个进程进入了阻塞状态

那需要再次强调的是 用户级线程是在用户视角能看到的 线程由线程库实现

就像那个很简单粗暴的循环 可以认为是一个最简单的线程库 那内核级线程才是操作系统视角能看到到的线程由操作系统

来负责管理 所以内核及现成才是处理及分配的单位 那对于我们介绍这几种多现成模型来说 大家主要是要理解他们各自的优缺点

另外 这个部分的内容比较容易考察 关于阻塞的问题 这个大家在课后习题当中会有体会

好的 那么以上就是这个小节的全部内容

推荐一个零声学院免费公开课程,个人觉得老师讲得不错,分享给大家:Linux,Nginx,ZeroMQ,MySQL,Redis,fastdfs,MongoDB,ZK,流媒体,CDN,P2P,K8S,Docker,TCP/IP,协程,DPDK等技术内容,立即学习

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1389399.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

人脸识别打卡系统的设计与应用!人脸识别打卡系统有什么用?

教育行业的快速日新月异,对信息化建设的要求也越来越高。学校物业管理成为保障学校正常运行的重要环节。然而,在实践中,由于服务人员数量不足、管理不规范等问题,服务质量往往难以保证物业对学校师生的服务质量。为了解决这一问题…

如果你正在学自动化测试,那么请你仔细看完这篇文章

接触了不少同行,由于他们之前一直做手工测试,现在很迫切希望做自动化测试,其中不乏工作5年以上的人。 本人从事软件自动化测试已经近5年,从server端到web端,从API到mobile,切身体会到自动化带来的好处与痛楚…

高级 Python 面试问题与解答

文章目录 专栏导读1.什么是PIP?2.什么是 zip 函数?3.Python 中的 __init __ () 是什么?4.Python 中的访问说明符是什么?5.Python 中的单元测试是什么?6.Python全局解释器锁(GIL)?7.P…

linux yum仓库

yum是基于rpm包构建的软件更新机制,能够自动解决软件包之间的依赖关系。 常用命令 查询 yum list [软件名] 显示可用的安装包,如果不加软件名则显示所有的可用包 yum info [软件名] 显示安装包的详细信息 如果不加软件名是显示所有包…

CF1178F2 Long Colorful Strip 题解 搜索

Long Colorful Strip 传送门 题面翻译 题目描述 这是 F 题的第二个子任务。F1 和 F2 的区别仅在对于 m m m 和时间的限制上 有 n 1 n1 n1 种颜色标号从 0 0 0 到 n n n,我们有一条全部染成颜色 0 0 0 的长为 m m m 的纸带。 Alice 拿着刷子通过以下的过…

MybatisPlus框架入门级理解

MybatisPlus 快速入门入门案例常见注解常用配置 核心功能条件构造器自定义SQLService接口 快速入门 入门案例 使用MybatisPlus的基本步骤: 1.引入MybatisPlus的起步依赖 MybatisPlus官方提供了starter,其中集成了Mybatis和MybatisPlus的所有功能&#…

Spring Cloud 微服务中 gateway 网关如何设置健康检测端点

主要是为了让 k8s 识别到网关项目已经就绪,但是又不想在里面通过 Controller 实现。因为在 Controller 中这样做并不是最佳实践,因为 Gateway 的设计初衷是专注于路由和过滤,而不是业务逻辑的处理。 在 Gateway 中配置健康检查端点可以通过以…

QT报错记录

Ubuntu22.04安装Qt之后启动Qt Creator报错: Fron 6.5.0, xcb-cursor0 or libxcb-cursor0 is needed to load the Qt xcb platforn plugin. Could not load. This application failed to start because no Qt platforn plugin could be initialized. Reinstalling t…

Qt vs开发将Graphics view提升 QChartview

1提升部件 2 添加Charts模块 3 在包含ui类的头文件添加QT_CHARTS_USE_NAMESPACE 或者添加 using namespace QtCharts #include <QtWidgets/QMainWindow> #include <QtCharts> #include "ui_mainwin.h" #include <qchartview.h> QT_CHARTS_USE_N…

k8s---pod控制器

pod控制器发的概念&#xff1a; 工作负载&#xff0c;workload用于管理pod的中间层&#xff0c;确保pod资源符合预期的状态。 预期状态&#xff1a; 1、副本数 2、容器重启策略 3、镜像拉取策略 pod出故障的出去等等 pod控制器的类型&#xff1a; 1、replicaset&#xf…

Star 72.4k!神仙级开源项目,真的一行代码都没有!

前言 在 GitHub 开源社区&#xff0c;我们经常能发现一些优秀的开源高分项目&#xff01;有时候为了找到最优秀的开源项目&#xff0c;却往往要在 GitHub 上搜罗很久&#xff0c;很消耗时间。 今天小编就给大家推荐一个近乎于完美的 GitHub 中文排行榜&#xff0c;在这里&…

java基础之线程练习题

1.关于线程设计&#xff0c;下列描述正确的是&#xff08;&#xff09; A.线程对象必须实现Runnable 接口 B.启动一个线程直接调用线程对象的 run()方法 C.Java 对多线程同步提供语言级的支持 synchronized D.一个线程可以包括多个进程 2.在java 中的线程模型包含&#xff0…

【刷题】leetcode 1 . 两数之和

两数之和 两数之和1 思路一 &#xff08;简单突破&#xff09;2 思路二 &#xff08;进行优化&#xff09;3 思路三 &#xff08;哈希表 我还不会&#xff09; 谢谢阅读Thanks♪(&#xff65;ω&#xff65;)&#xff89;下一篇文章见&#xff01;&#xff01;&#xff01; 两数…

发票系统对接诺诺平台

诺诺平台判断设备不在线&#xff0c;导致开票失败 代码方面优化&#xff1a;调用接口的时候&#xff1a;是否先调用在线状态检测接口&#xff0c;确认开票设备是在线的状态 &#xff0c;在调用诺诺平台&#xff0c;不在线直接拦截&#xff1b;例如&#xff1a;这个原理就类似于…

三使用Docker Hub管理镜像

使用Docker Hub管理镜像 Docker Hub是Docker官方维护的Docker Registry&#xff0c;上面存放着很多优秀的镜像。不仅如此&#xff0c;Docker Hub还提供认证、工作组结构、工作流工具、构建触发器等工具来简化我们的工作。 前文已经讲过&#xff0c;我们可使用docker search 命…

虚拟机连接(与主机断开连接)U盘的按钮为灰色之解决方法

在WIN11中&#xff0c;虚拟机“连接(与主机断开连接)U盘”选项为灰色&#xff0c;解决方法如下&#xff1a; 1、关闭虚拟机电源&#xff0c;得到下面的界面&#xff1a; 2、根据上述提示&#xff0c;找到虚拟机所在磁盘 3、配置文件属性见下图&#xff1a; 4、使用记事本打开…

C++力扣题目98--验证二叉搜索树

给你一个二叉树的根节点 root &#xff0c;判断其是否是一个有效的二叉搜索树。 有效 二叉搜索树定义如下&#xff1a; 节点的左子树只包含 小于 当前节点的数。节点的右子树只包含 大于 当前节点的数。所有左子树和右子树自身必须也是二叉搜索树。 示例 1&#xff1a; 输入…

在Overleaf中解决IEEE LaTeX模板不能显示中文问题

解决IEEE的Latex模板不能显示中文的问题 写在最前面编译器选择XeLatex导入CTeX包IEEE单栏转换为双栏如何在Overleaf中解决IEEE LaTeX模板显示中文问题&#xff1a;一些其他的补充引言问题描述准备工作为什么中文字符在IEEE LaTeX模板中显示有问题——了解LaTeX编码的基础概念 关…

【JavaEE】CAS

作者主页&#xff1a;paper jie_博客 本文作者&#xff1a;大家好&#xff0c;我是paper jie&#xff0c;感谢你阅读本文&#xff0c;欢迎一建三连哦。 本文于《JavaEE》专栏&#xff0c;本专栏是针对于大学生&#xff0c;编程小白精心打造的。笔者用重金(时间和精力)打造&…

工会排队:零撸式消费新体验,引爆市场热度

随着消费市场的日益竞争&#xff0c;消费者对于购物体验的要求也越来越高。传统的促销方式已经无法满足消费者的需求&#xff0c;于是&#xff0c;一种全新的消费模式——工会排队应运而生。这种创新的消费模式&#xff0c;让消费者在购物的同时&#xff0c;还能获得实实在在的…