前言:教育的公平才是最大的公平,本科和专科还是有点差别的。时间长点学方面会充实些。
先给个结论:I/O多路复用技术(就是大家经常说的事件循环)实际上,事件驱动模型还有另外一个名字,而且更加出名的名字:io多路复用。

噢,要讲明白io多路复用之前,我们还要知道一些概念,不要担心,我会用很傻的方式告诉你。

  1. 1.1

小张找基友小鹏小张第一次来到小鹏的宿舍楼,发现这个宿舍楼有一大堆的楼妈,为啥?因为学校竟然请了一堆楼妈来管理宿舍楼里的每一个宿舍,结果搞得一大堆楼妈唧唧咋咋的,乌烟瘴气。重要的就是学校会给每个楼妈都发工资。小张顿时觉得,这个学校没药救了。没错,现实中已经没有这种傻逼现象了,学校也不会傻到这种程度为每一个宿舍都请一个楼妈来管理。

  1. 1.2

过了几十年,小张的儿子来找小鹏的儿子不巧,过了一二十年,小张的儿子和小鹏的儿子也上了同一所学校,小张张要来找小鹏鹏。小张张听了父亲说,这个学校的舍管特别傻逼,会有一堆,能烦死你。结果小张张来到了宿舍楼,发现现在只有一个楼妈了,哎哟,不错嘛,学校终于没那么傻逼了。但是,这个楼妈比较傻,小张张去问她:小鹏鹏在哪个寝室啊?她说,我也不知道啊。我带你上去找吧?于是乎,小张张和楼妈挨个挨个的找宿舍,最终花了半天时间找到了小鹏鹏…(小张张尿了。

  1. 1.3

又过去了差不多20年此时,学校已经不是那个学校,张和鹏都挂得差不多了。新生代小春来找小丽,小春来到了这个宿舍,找到了楼妈。这个楼妈就比较聪明了,每当一个学生入住新宿舍的时候,她就记录下这个人的名字,学号,电话,以及宿舍房号。当小春找小丽的时候,楼妈掏出眼镜,查表,马上就能知道小丽在哪里了,小春几分钟就到达了小丽的宿舍…

--------------------------------------对应到编程界--------------------------
在最开始的时候,为了实现一个服务器可以支持多个客户端连接,人们想出了fork/thread等办法,当一个连接来到的时候,就fork/thread一个进程/线程去接收并且处理请求,然而,当时估计是大家都穷吧,没啥钱买电脑,所以这个模型一直很好用,过去几十年都没有问题。
但是时代发展了,1980年代,计算机网络开始成型,越来越多的用户进行网络连接(其实也没多少),但是之前的fork/thread模型就不行了,太辣鸡了。(回想一下小张和小鹏与一大堆楼妈的故事)

(select函数发明)

1983年,人们终于意识到了这种问题,所以发明了一种叫做「IO多路复用」的模型,这种模型的好处就是「没必要开那么多条线程和进程了」,一个线程一个进程就搞定了。随着计算机业务的增长,这种IO多路复用的模型看似太傻逼了点,回想一下小张张和小鹏鹏:
1宿舍楼里有可能有上百间宿舍
2为了寻找到其中一间宿舍,你必须得一间一间去找,浪费时间
对应的编程模型就是:一个连接来了,就必须遍历所有已经注册的文件描述符,来找到那个需要处理信息的文件描述符,如果已经注册了几万个文件描述符,那会因为遍历这些已经注册的文件描述符,导致cpu爆炸。
直到2002年,互联网时代爆炸,数以千万计的请求在全世界范围内发来发去,服务器大爆炸,人们通过改进「IO多路复用」模型,进一步的优化,发明了一个叫做

epoll的方法

。这个方法就是小春和小丽故事里聪明的楼妈。

事件驱动的一个缺点

事件驱动不是无敌的,在事件驱动模型中,处理事件的进程一定是单线程的。在现代工业中我们会面临两个问题:
1单线程模型不能有阻塞,一旦发生任何阻塞(包括计算机计算延迟)都会使得这个模型不如多线程。另外,单线程模型不能很好的利用多核cpu
2既然不能有阻塞,那我们只有用多线程去做异步io,那马上就会面临回掉地狱。
为了解决我上述说的两个问题人们做出了一些改进:
1利用多进程,每个进程单条线程去利用多核CPU。但是这又引入了新的问题:进程间状态共享和通信。但是对于提升的性能来说,可以忽略不计。
2发明了协程。

协程

协程的概念是相对多进程或者多线程来说的,他是一种协作式的用户态线程
1与之相对的,线程和进程是以抢占式执行的,意思就是系统帮我们自动快速切换线程和进程来让我们感觉同步运行的感觉,这个切换动作由系统自动完成
2协作式执行说的就是,想要切换线程,你必须要用户手动来切换
协程为什么那么快原因就是因为,无需系统自动切换(系统自动切换会浪费很多的资源),而协程是我们用户手动切换,而且是在同一个栈上执行,速度就会非常快而且省资源。
但是,协程有他自己的问题:协程只能有一个进程,一个线程在跑,一旦发生IO阻塞,这个程序就会卡住。
所以我们要使用协程之前,必须要保证我们所有的IO都必须是非阻塞的。

3.1 所有IO非阻塞/异步IO
IO无非就是几种
1.读(硬盘的)的
2.写(硬盘的)的
3.网络请求(读和写)

所有的读和写,网络请求接口都要设置成非阻塞式的,当系统内核把这些玩意儿执行完毕以后,再通过回调函数,通知用户处理。在用户空间上来看,我们就一直保持在一个线程,一个进程之中,因此,这种速率极高!
为什么Nodejs并发量会那么变态的原因就是这一点:nodejs因为js线程只有一条(底层的IO使用多线程来实现非阻塞),为了让程序不会卡住,就一定要把所有的IO变成非阻塞异步,通过回调来告诉用户。
那么问题就来了:我们进行IO操作的目的是因为我们想获得某些数据然后再开始进行操作,所以我们不得不在回调函数中操作。我们在回调函数中获取到我们想要的数据,我们依靠这段数据又他妈的想要获取另外一段数据,怎么办?继续回调。一两层你可能就觉得不行了,45678层呢?nginx是个好东东。


3.2 协程真正目的
协程的真正目的其实并不是为了解决高并发而存在的,而是为了解决这种蛋痛的无限回调而存在的
使用协程之后,我们就可以像使用「同步」的方法去写异步的调用,刚刚开始听到的时候,你可能会懵逼了。
不过没事,等我们写代码的时候就会深刻体会了。

总结:在接下去的web时代里,异步io配合协程就是主导。i/O多路复用技术已经出现了快40年了,不是新东西

作者:方正
链接:https://www.zhihu.com/question/28594409/answer/345897182
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

整理 云草学长 by 20210429

概念 多路复用 到底是个啥?通俗易懂的理解相关推荐

  1. [通俗易懂]深入理解TCP协议(下):RTT、滑动窗口、拥塞处理

    转自即时通讯网:http://www.52im.net/ 前言 此文为系列文章的下篇,如果你对TCP不熟悉的话,请先看看上篇<[通俗易懂]深入理解TCP协议(上):理论基础> . 上篇中, ...

  2. [通俗易懂]深入理解TCP协议(上):理论基础

    转自即时通讯网:http://www.52im.net/ 前言 TCP是一个巨复杂的协议,因为他要解决很多问题,而这些问题又带出了很多子问题和阴暗面.所以学习TCP本身是个比较痛苦的过程,但对于学习的 ...

  3. 欧拉角死锁_刚体运动学最通俗易懂的理解万向节死锁

    在网上看了很多所谓的通俗易懂的理解万向节死锁的文章,甚至动画. 可能是我想象力有问题,实在是理解不了: 如果xyz表示机体坐标系,那机体坐标系永远不可能重合,也就不会出现第二种状态. 恰巧,我们刚看了 ...

  4. 【大话Java面试】-如何通俗易懂的理解Redis的回收算法LRU?

    如何通俗易懂的理解LRU算法? 1.LRU是什么? LRU全称Least Recently Used,也就是最近最少使用的意思,是一种内存管理算法,最早应用于Linux操作系统. LRU算法基于一种假 ...

  5. 02-CPU基础知识:通俗易懂方式理解主频、核心、线程、缓存、架构

    我们通常会将CPU比喻为人类的大脑,是计算机的核心硬件,决定了一台电脑的运算性能好坏.我们在选购CPU的时候,通常都会在网上查询处理器型号参数,主要是看主频.核心.线程.缓存.架构等参数,那么对于小白 ...

  6. 通俗易懂彻底理解十倍交叉验证法

    通俗易懂彻底理解10-fold cross-validation method(十倍交叉验证法) 十倍交叉验证法: 将所有数据分为十份,然后将每一份作为验证集,其他作为训练集来进行训练和验证.在这一过 ...

  7. Netty系列进阶篇一:阻塞和多路复用到底是个啥?

    文章目录 一.进阶篇:Netty封装了什么? 二.刨根问底:到底什么是阻塞?什么是多路复用器? 1.操作系统基础 1-1 用户态与内核态 1-2 系统调用 1-3 File Descriptor 文件 ...

  8. 公钥和私钥怎么生成_有趣图文帮你通俗易懂地理解公钥和私钥的区别以及与CA证书等概念...

    导读:Linux系统上非对称性加密需要用到公钥.私钥.也常涉及到数字签名.数字证书.CA证书等概念.本文通过有趣的海绵宝宝和它小伙伴故事搭配有趣的图片形式来阐述这些概念,希望能帮助读者更简单易懂地理解 ...

  9. ORM的概念, ORM到底是什么

    概念 对象-关系映射(OBJECT/RELATIONALMAPPING,简称ORM),是随着面向对象的软件开发方法发展而产生的.用来把对象模型表示的对象映射到基于S Q L 的关系模型数据库结构中去. ...

最新文章

  1. opengl嵌入pyqt5编译的分割窗口中
  2. 中国科学院院士梅宏:云计算这十年
  3. Elasticsearch java客户端调用cat服务
  4. JBoss Portal CAS 的配置
  5. 【转】深入浅出理解有限状态机
  6. 哪个计算机无法做到双屏显示,怎么启用双屏显示设置【图文介绍】
  7. java并发包作者lee_Java的一些并发包
  8. linux 系统自动挂起,linux 系统挂起
  9. htnl 点击系统记录显示在右侧_软网推荐:时间管理者 记录工时与薪酬
  10. python 数学期望_数学期望(离散型和连续型)
  11. 【Word】利用域代码快速实现自定义编号
  12. 苹果手机的微信记录怎么恢复?奉上超好用的恢复技巧,拿走不谢
  13. C++ 将二叉树以前序遍历的顺序转换成链表
  14. 去哪儿网被央视曝光,其实智慧旅行可以做到更多
  15. 显示器几种常见的接口
  16. Echarts X轴内容过长自动隐藏,鼠标移动上去显示全部
  17. 12306中/otn/HttpZF/logdevice?algID 与 /otn/HttpZF/GetJS 的关系
  18. c语言深度剖析(2)—有符号与无符号
  19. 在docker中出现的僵尸进程怎么处理
  20. Python: 从pcap文件中提取每个TCP session的payload

热门文章

  1. 2008R2服务器提示 由于远程,Server2008R2远程桌面提示出现身份验证错误的问题解决...
  2. PyCharm添加Anaconda中的虚拟环境,Python解释器出现Conda executable is not found
  3. OUTLOOK的通讯录导入问题
  4. socketio python_python3--socketIO_client 摸索怕坑指南
  5. asterisk的基本配置
  6. permute和view
  7. 索引原理:联合索引(最左前缀原则)
  8. Mybatis与Spring集成原理
  9. Java学习笔记之JDBC
  10. 前锋PHP的大并发集群技术,高并发下,php、swoole与redis实现的秒杀功能