当前位置:网站首页>并发模型和I/O模型介绍
并发模型和I/O模型介绍
2022-08-02 23:55:00 【Linux服务器开发】
并发模型
常见的并发模型一般包括3类,基于线程与锁的内存共享模型,actor模型和CSP模型,其中尤以线程与锁的共享内存模型最为常见。由于go语言的兴起,CSP模型也越来越受关注。基于锁的共享内存模型与后两者的主要区别在于,到底是通过共享内存来通信,还是通过通信来实现访问共享内存。由于actor模型和CSP模型,本人并不是特别了解,我主要说说最基本的并发模型,基于线程与锁的内存共享模型。
为什么要并发,本质都是为了充分利用多核CPU资源,提高性能。但并发又不能乱,为了保证正确性,需要通过共享内存来协调并发,确保程序正确运转。无论是多进程并发,还是多线程并发,要么通过线程间互斥同步(spinlock,rwlock,mutex,condition,信号量),要么通过进程间通信(共享内存,管道,信号量,套接字),本质都是为了协同。多线程和多进程本质类似,尤其是linux环境下的pthread库,本质是用轻量级进程实现线程。下面以网络服务为例,简单讨论下多线程模型的演进。
最简单的模型是单进程单线程模型,来一个请求处理一个请求,这样效率很低,也无法充分利用系统资源。那么可以简单的引入多线程,其中抽出一个线程监听,每来一个请求就创建一个工作线程服务,多个请求多个线程,这就是多线程并发模型。这种模式下,资源利用率是上去了,但是却有很多浪费,线程数与请求数成正比,意味着频繁的创建/销毁线程开销,频繁的上下文切换开销,这些都是通过系统调用完成,需要应用态到内核态的切换,导致sys-cpu偏高,资源并没有充分利用在处理请求上。
为了缓解这个问题,引入线程池模型,简单来说,就是预先创建好一批线程,并且加大线程的复用能力,将线程数控制在一定数目内,缓解上下文切换开销。以MySQL线程池为例,原来多线程模型是单连接单线程,现在变成单语句单线程,提高了线程复用效率。如果线程在执行过程中遇到等待(锁等待,IO等待),那么线程挂起,并减少活跃线程数,告知线程池系统活跃线程可能不够,需要追加线程,然后等系统空闲时,再减少线程数目,做到根据系统负载平衡线程数目。为了做到极致,更进一步减少上下文切换开销,引入了协程,协程只是一种用户态的轻量线程,它运行在用户空间,不受系统调度。它有自己的调度算法。在上下文切换的时候,协程在用户空间切换,而不是陷入内核做线程的切换,减少了开销。协程的并发,是单线程内控制权的轮转,相比抢占式调度,协程是主动让权,实现协作。协程的优势在于,相比回调的方式,写的异步代码可读性更强。缺点在于,因为是用户级线程,利用不了多核机器的并发执行。简单总结下:
单线程-->(单线程轮询处理,太慢)
多线程-->(多线程会频繁地创建、销毁线程,这对系统也是个不小的开销。这个问题可以用线程池来解决。)
线程池-->(仍然有多线程上下文切换的问题,调度由内核调度)
协程-->(应用层调度,不touch内核)
I/O模型
linux中所有物理设备对于系统而言都可以抽象成文件,包括网卡,对应的就是套接字,磁盘对应的文件,以及管道等。因此所有对物理设备的读写操作都可以抽象为IO操作,典型的IO操作模型分为以下几类,阻塞IO,非阻塞IO,I/O多路复用,异步非阻塞IO以及异步IO等。
【文章福利】另外小编还整理了一些C/C++后台开发教学视频,相关面试题,后台学习路线图免费分享,需要的可以自行添加:Q群:720209036 点击加入~ 群文件共享
小编强力推荐C++后台开发免费学习地址:C/C++Linux服务器开发高级架构师/C++后台开发架构师https://ke.qq.com/course/417774?flowToken=1013189
IO模型分类
阻塞I/O--> 原生的read/write系统调用,默认导致线程阻塞;
非阻塞I/O -->通过指定系统调用read/write的参数为非阻塞,告知内核fd没就绪时,不阻塞线程,而是返回一个错误码,应用死循环轮询,直到fd就绪;
I/O多路复用-->(select/poll/epoll),对通知事件堵塞,对于I/O调用不堵塞。
异步I/O(异步非阻塞)-->告知内核某个操作(读写I/O),并让内核在整个操作(包括将数据复制到我们的进程缓冲区)完成后通知。
I/O多路复用
常见的I/O多路复用主要用于网络IO场景,主要有select,poll和epoll机制。对比同步I/O,实际上是对I/O请求加了一层代理,由这些代理去监听通知事件(是否网络包到来),然后再通知用户去读写数据。这种方式也是一种阻塞I/O,代理对通知事件阻塞,这里的代理一般指监听线程。对比select,poll提升了最大支持文件描述符数目,从1024提升到65535,MySQL中的半同步复制还因为使用select的这个限制,导致半同步中断的bug(链接)。
对比select和poll机制,epoll通过事件表管理用户感兴趣的事件,无需反复传入用户感兴趣事件,处理事件通知的时间复杂度是O(1),而select,poll机制的时间复杂度是O(N)。另外select/poll只能工作在LT模式(水平触发模式);而epoll不仅支持LT模式,还支持ET模式(边缘触发模式)。两种模式的主要区别是,有数据可读时,LT模式会不停的通知,直到数据被获取,这种模式不用担心通知事件丢失;ET模式只会通知一次,因此对比LT少很多epoll系统调用,效率更高。epoll对编程要求高,需要细致的处理每个请求,否则容易发生丢失事件的情况。从本质上讲,与LT相比,ET模型是通过减少系统调用来达到提高并行效率的。
libev/libeasy
epoll很好用,但是要使用epoll,fd,signal,timer分别要采用不同的机制才能一起工作。libev第一个要做的事情就是把系统资源统一成一种调用方式。因为都需要在读写事件就绪后自己负责进行读写,也就是读写过程是阻塞的。libev的核心是事件处理框架,最常见的是就是一个所谓的Reactor事件处理框架和设计模式。Reactor对象负责实现主循环(其中有事件分离器的调用),定义事件处理接口,用户程序向Reactor注册事件回调的实现类(从接口继承),Reactor主循环在收到事件的时候调用相应的回调函数。libeasy实现类似libev和libevent的功能,包括HTTP服务器等,不同的是,它基于libev做了包装,提供了同一个的资源fd和loop机制,线程池,异步框架等实现。
AIO
说到AIO,一般是说磁盘的异步I/O,linux早期的版本并没有真正的AIO接口,所谓的AIO其实是多线程模拟的,在应用态完成。具体而言就是有一个队列存储IO请求,通过一组工作线程提取任务,并发起同步IO,待IO完成后,再通知用户已经完成了。对于用户而言,由于是提交IO请求后就直接返回,然后再被通知IO已经完成,所以可以认为是异步I/O,这种异步I/O实现机制主要指POXIS AIO,MySQL的InnoDB引擎也实现了一套类似的AIO机制。后面linux内核引入了真正的AIO,主要区别在于发起I/O调用不再是同步调用,IO请求统一在内核层面排队,并且一次可以提交一批异步IO请求,然后通过轮询或者回调的方式接收完成通知即可。相比于POXIS AIO,底层有更多的IO并行,IO和CPU能充分并发,大大提升性能。在使用中,通过-lrt链接使用AIO库是POXIS接口,而通过-laio链接使用的AIO库是linux Native AIO接口。常用接口包括 io_setup,io_destroy,io_submit,io_cacel和io_getevents等。
对比
同步IO:
优点:简单
缺点:IO阻塞,无法充分利用IO和CPU资源,效率低
Native AIO:
优点:AIO可以支持一次发送多个不连续的异步IO请求,性能更好(同步IO需要发送多次)
缺陷:需要文件系统支持O_DIRECT选项,如果不支持,io_submit实际上是“退化”成同步操作。
POSIX AIO:
优点:不依赖O_DIRECT选项,有一定的合并能力(相邻地址的请求,可以做merge)。
缺点:并发的IO请求受限于线程数目;另外就是,可能慢速磁盘,可能导致其它新的请求没有及时处理(工作线程数不够了)。
参考资料
推荐一个零声教育C/C++后台开发的免费公开课程,个人觉得老师讲得不错,分享给大家:C/C++后台开发高级架构师,内容包括Linux,Nginx,ZeroMQ,MySQL,Redis,fastdfs,MongoDB,ZK,流媒体,CDN,P2P,K8S,Docker,TCP/IP,协程,DPDK等技术内容,立即学习
边栏推荐
猜你喜欢
随机推荐
js显示隐藏手机号
DownMusic summary record
Last Common Ancestor (LCA) Study Notes | P3379 【Template】Least Common Ancestor (LCA) Problem Solution
fifa将采用半自动越位技术计算进球
scala 集合通用方法
有奖提问|《新程序员》专访“Apache之父”Brian Behlendorf
解决错误:Optional int parameter ‘pageSize‘ is present but cannot be translated into a null value due to
What is the matter that programmers often say "the left hand is knuckled and the right hand is hot"?
基于飞腾平台的嵌入式解决方案案例集 1.0 正式发布!
3、Xendesktop更改发布桌面的显示名称(MCS静态桌面)
年近30 ,4月无情被辞,想给划水的兄弟提个醒...
Visual Studio中vim模拟器
Understand the next hop address in the network topology in seconds
D experimental new anomaly
DownMusic总结记录
【多线程】线程与进程、以及线程进程的调度
CIO修炼手册:成功晋升CIO的七个秘诀
公司招个程序员,34岁以上两年一跳的不要,开出工资以为看错了
2022 Shandong International Youth Eye Health Industry Exhibition, Vision Health Exhibition, Optometry Exhibition
2022中国眼博会,山东眼健康展,视力矫正仪器展,护眼产品展