异步开发的终极答案—协程

2024-06-21 20:20

本文主要是介绍异步开发的终极答案—协程,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

我们在之前的文章中讲过,在并发场景下,传统的基于多线程的命令式开发模型虽然比较简单,但并发数高了之后资源占用较高,大量线程会阻塞;而响应式编程模式我们可以通过异步化处理提升系统资源的利用效率,但异步开发有违人的直觉,门槛比较高。作为成年人,我们肯定希望全都要呀,那么能实现吗?今天我们就来介绍另一种并发的开发模式—协程

背景知识

在正式介绍协程的定义时,我们还需要先了解一些操作系统的基础知识:

用户态与内核态

在现代的操作系统中,为了有效减少内核资源的访问和冲突,一般会将功能划分为不同的层级,与硬件关系紧密相关的模块(中断处理)以及运行频率较高的模块(时钟,进度调度等),都会将它们常驻内存,这些就构成了通常所谓的OS内核,这样安排主要基于两个目的:

  1. 有效减少内核资源的访问及冲突,提升访问效率
  2. 对这些软件进行保护,防止遭受其他应用程序的破坏

因此OS的运行状态又分为了两种:

  • 内核态:它具有较高的特权,能执行一切指令,访问所有的寄存器和存储区,OS内核都运行在内核态;
  • 用户态:它具有较低特权的执行状态,仅能执行规定的指令,访问指定的寄存器和存储区。一般情况下,应用程序只能在用户态运行。

在这里插入图片描述

用户态的应用程序有时候也需要运行一些敏感操作,比如访问硬件(磁盘,网卡等),创建进程等,这些操作必须要通过一种叫做系统调用的形式去实现,系统调用可以看作是OS内核暴露给用户态应用程序的一些接口和函数,这里不做过多解释。

当用户态应用程序通过系统调用访问内核态的资源时,就涉及到运行上下文的切换,这种切换是有开销的,一般需要几十纳秒到数微秒左右的时间。

N:M线程模型

有了上面的介绍,我们可以再回顾一下我们经常使用的线程的概念,线程其实是为了并发和资源共享从而抽象出来的一种基本的调度单元,那谁来调度和管理线程呢?其实也可以分成两类:

  • 用户线程:由编程语言或者应用程序自行管理和调度,不需要内核的支持,内核也不会感知到,消耗资源非常少。
  • 内核线程:由操作系统创建,管理以及调度,只运行在内核态,资源消耗较大。

但单纯的用户线程没有什么意义,因为从操作系统的视角,只能感知到内核线程,所有的系统的调用和计算也只能通过内核线程才能完成,所以用户线程必须得映射到内核线程。这就是所谓得N:M线程模型,N是用户线程,M是内核线程,Java在1.2版本前是N:1的,即所有的用户线程都会对应到一个内核线程中,这样做线程的操作较快且消耗较低,并且线程数量不受操作系统限制。但缺点也很明显,由于只有一个内核线程,所谓的并发都是伪并发,只有内核线程阻塞了,其上的所有用户线程都会阻塞,更无法发挥多核CPU的优势

在这里插入图片描述

1.2之后的Java版本都是1:1的映射模式,即一个用户线程对应一个内核线程,这样每个线程的创建、调度、销毁都需要内核的支持,每次线程的创建、切换都会设计用户状态/内核状态的切换,性能开销比较大,都能够真正利用多核CPU的能力。

~~1:1图.png~~

线程的调度

为了有效的使用系统资源,确保公平性和及时响应,线程是需要经过调度才能执行的,不然就乱套了。主流的调度算法一般有两种:

  • 抢占式调度: 管理者能在任意时候中断正在运行的任务,并将CPU分配给另一个任务。
  • 协作式调度: 任务在适当的时机主动放弃CPU的控制权,管理者不强制中断任务,调度这个动作是由多个任务主动协作来实现的。

抢占式调度初看起来非常的不讲理,如果某个线程马上就要执行完了确被强迫让出执行权,下次还要等待重新调度才能执行,这样会无端多出很多上下文切换的开销。但如果站在操作系统得视角,就能理解这样得无奈了,因为操作

这篇关于异步开发的终极答案—协程的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1082234

相关文章

大学湖北中医药大学法医学试题及答案,分享几个实用搜题和学习工具 #微信#学习方法#职场发展

今天分享拥有拍照搜题、文字搜题、语音搜题、多重搜题等搜题模式,可以快速查找问题解析,加深对题目答案的理解。 1.快练题 这是一个网站 找题的网站海量题库,在线搜题,快速刷题~为您提供百万优质题库,直接搜索题库名称,支持多种刷题模式:顺序练习、语音听题、本地搜题、顺序阅读、模拟考试、组卷考试、赶快下载吧! 2.彩虹搜题 这是个老公众号了 支持手写输入,截图搜题,详细步骤,解题必备

Eclipse+ADT与Android Studio开发的区别

下文的EA指Eclipse+ADT,AS就是指Android Studio。 就编写界面布局来说AS可以边开发边预览(所见即所得,以及多个屏幕预览),这个优势比较大。AS运行时占的内存比EA的要小。AS创建项目时要创建gradle项目框架,so,创建项目时AS比较慢。android studio基于gradle构建项目,你无法同时集中管理和维护多个项目的源码,而eclipse ADT可以同时打开

Python应用开发——30天学习Streamlit Python包进行APP的构建(9)

st.area_chart 显示区域图。 这是围绕 st.altair_chart 的语法糖。主要区别在于该命令使用数据自身的列和指数来计算图表的 Altair 规格。因此,在许多 "只需绘制此图 "的情况下,该命令更易于使用,但可定制性较差。 如果 st.area_chart 无法正确猜测数据规格,请尝试使用 st.altair_chart 指定所需的图表。 Function signa

黑客帝国终极大Boss的角色是啥?

《黑客帝国》是非常经典的科幻电影,第一部于1999年3月31日上映。时隔20多年,人类正在一步步地朝着电影中描述的矩阵世界发展。今年正好是人工智能大规模发展的一年,再加上最近Open AI的宫斗戏,让一切都变得神秘莫测。 如果还没有看过《黑客帝国》的话,强烈推荐去看看。今天不聊电影赏析方面的事,我也不专业,今天还是借电影聊聊企业经营管理方面的事情。先抛个问题,您知道黑客帝国里终极大Boss的角色

WDF驱动开发-WDF总线枚举(一)

支持在总线驱动程序中进行 PnP 和电源管理 某些设备永久插入系统,而其他设备可以在系统运行时插入和拔出电源。 总线驱动 必须识别并报告连接到其总线的设备,并且他们必须发现并报告系统中设备的到达和离开情况。 总线驱动程序标识和报告的设备称为总线的 子设备。 标识和报告子设备的过程称为 总线枚举。 在总线枚举期间,总线驱动程序会为其子 设备创建设备对象 。  总线驱动程序本质上是同时处理总线枚

JavaWeb系列六: 动态WEB开发核心(Servlet) 上

韩老师学生 官网文档为什么会出现Servlet什么是ServletServlet在JavaWeb项目位置Servlet基本使用Servlet开发方式说明快速入门- 手动开发 servlet浏览器请求Servlet UML分析Servlet生命周期GET和POST请求分发处理通过继承HttpServlet开发ServletIDEA配置ServletServlet注意事项和细节 Servlet注

手把手教你入门vue+springboot开发(五)--docker部署

文章目录 前言一、前端打包二、后端打包三、docker运行总结 前言 前面我们重点介绍了vue+springboot前后端分离开发的过程,本篇我们结合docker容器来研究一下打包部署过程。 一、前端打包 在VSCode的命令行中输入npm run build可以打包前端代码,出现下图提示表示打包完成。 打包成功后会在前端工程目录生成dist目录,如下图所示: 把

Sapphire开发日志 (十) 关于页面

关于页面 任务介绍 关于页面用户对我组工作量的展示。 实现效果 代码解释 首先封装一个子组件用于展示用户头像和名称。 const UserGrid = ({src,name,size,link,}: {src: any;name: any;size?: any;link?: any;}) => (<Box sx={{ display: "flex", flexDirecti

ROS2从入门到精通4-4:局部控制插件开发案例(以PID算法为例)

目录 0 专栏介绍1 控制插件编写模板1.1 构造控制插件类1.2 注册并导出插件1.3 编译与使用插件 2 基于PID的路径跟踪原理3 控制插件开发案例(PID算法)常见问题 0 专栏介绍 本专栏旨在通过对ROS2的系统学习,掌握ROS2底层基本分布式原理,并具有机器人建模和应用ROS2进行实际项目的开发和调试的工程能力。 🚀详情:《ROS2从入门到精通》 1 控制插

JavaWeb 学习笔记 spring+jdbc整合开发初步

JdbcTemplate类是Spring的核心类之一,可以在org.springframework.jdbc.core中找到它。JdbcTemplate类在内部已经处理数据库的建立和释放,可以避免一些常见的错误。JdbcTemplate类可直接通过数据源的应用实例化,然后在服务中使用,也可在xml配置中作为JavaBean应用给服务使用直接上一个实例步骤1.xml配置 <?xml version