两种高效的并发模式

62 篇文章 56 订阅
56 篇文章 1 订阅

并发编程的目的是让程序”同时”执行多个任务。如果程序是计算密集型的,并发编程并没有什么优势,反而由于任务的切换使效率降低。但如果程序是I/O密集型的,那就不同了。
I/O操作通常分为两个阶段,即等待和数据搬迁,通常等待所花费的时间比较多。而I/O操作的速度远远低于CPU的计算速度,所以让程序阻塞在I/O操作将浪费大量的时间。如果程序有多个执行线程,则当前被I/O操作阻塞的线程可以放弃CPU,并将执行权限转移到其他线程。这样一来,CPU就可以做更多的事情了。
并发模式是指I/O处理单元和多个逻辑单元之间协调完成任务的方法,服务器主要有两种并发编程模式:半同步/半异步(half-sync/half-async)模式和领导者/追随者(Leader/Followers)模式。

一、半同步/半异步模式
1、半同步/半异步中的同步和异步
在半同步/半异步模式中的”同步”和”异步”与I/O模型中的同步和异步是完全不相同的两个概念。在并发模式中,”同步”指的是程序完全按照代码序列的顺序执行,”异步”指的是程序的执行需要系统事件来驱动。常见的系统事件的驱动包括中断、信号等。
例:
这里写图片描述

这里写图片描述

2、同步线程和异步线程
按照同步方式运行的线程称为同步线程,同步线程的效率比较低,实时性查,但是逻辑简单。
按照异步方式运行的线程称为异步线程,异步线程的效率比较高,实时性强,但是异步方式执行程序比较复杂,难于调试和扩展,不适合大量的并发。
因此对于服务器这种即要求较好的实时性,又要求并发性的应用程序,同时使用同步线程和异线程是一种比较好的模式。

3、半同步/半异步模式
在半同步/半异步模式中,同步线程用于处理客户逻辑,异步线程用于处理I/O事件。异步线程监听到客户请求之后就将其封装成请求对象并插入到请求队列中。请求队列将通知某个工作在同步模式的工作线程来读取并处理该请求对象。

工作流程:
这里写图片描述

4、半同步/半反应堆模式(half-sync/half-reactive模式)
半同步/半反应堆模式是半同步/半异步模式的一种变体。
其结构如下图:
这里写图片描述

在上图中,异步线程只有一个,由主线程充当,负责监听socket上的事件。如果监听socket上有新的连接请求到来,主线程就接受新的连接socket,然后往epoll内核事件表中注册该socket上的读写事件。如果连接socket上有读写事件发生,即有新的客户请求到来或有数据要发送至客户端,主线程就将该连接socket插入到请求队列中,所有工作线程都睡眠在请求队列上,当有任务到来时,他们通过竞争来获取任务的接管权。
由于主线程插入请求队列中的任务是就绪的连接socket,所以该半同步/半反应堆模式所采用的事件处理模式是Reactor模式,即工作线程要自己从socket上读写数据。当然,半同步/半反应堆模式也可以用模拟的Proactor事件处理模式,即由主线程来完成数据的读写操作,此时主线程将应用程序数据、任务类型等信息封装为一个任务对象,然后将其插入到请求队列。

半同步/半反应堆模式的缺点:
主线程和工作线程共享请求队列,因而请求队列是临界资源,所以对请求队列操作的时候需要加锁保护。
每个工作线程在同一时间只能处理一个客户请求。如果客户数量增多,则请求队列中堆积任务太多,客户端的响应会越来越慢。如果增多工作线程的话,则线程的切花也将消耗大量的CPU时间。

5、高效的半同步/半异步模式
在半同步/半反应堆模式中,每个工作线程同时只能处理一个客户请求,如果并发量大的话,客户端响应会很慢。如果每个工作线程都能同时处理多个客户链接,则就能改善这种情况,所以就有了高效的半同步/半异步模式。
其结构如图:
这里写图片描述

主线程只管监听socket,当有新的连接socket到来时,主线程就接受连接并返回新的连接socket给某个工作线程。此后该新连接socket上的任何I/O操作都由被选中的工作线程来处理,直到客户端关闭连接。当工作线程检测到有新的连接socket到来时,就把该新的连接socket的读写事件注册到自己的epoll内核事件表中。
主线程和工作线程都维持自己的事件循环,他们各自独立的监听不同事件。因此在这种高效的半同步/半异步模式中,每个线程都工作在异步模式中,所以它并非严格意义上的半同步/半异步模式。

二、领导者/追随者模式(Leader/Followers)
1、什么是领导者/追随者模式
领导者/追随者模式是多个工作线程轮流获得事件源集合,轮流监听、分发并处理事件的一种模式。
2、领导者/追随者模式的执行流程
在任意时间,程序都仅有一个领导者线程,他负责监听I/O事件。
而其他线程则都是追随者,他们休眠在线程池中等待成为新的领导者。
当前的领导者如果检测到I/O事件,首先要从线程池中推选出新的领导者线程,然后他自己去处理I/O事件。
新的领导者等待新的I/O事件。
处理I/O事件的线程处理完毕之后,就会变成一个追随者,直到再次被唤醒。

3、领导者/追随者模式中线程的角色
L/F模式中线程所担任的角色有三种,领导者、追随者、工作者。
领导者:负责监听I/O事件,等到事件到来之后要在线程池中选出一个新的领导者。
追随者:休眠在线程池中,等待成为新的领导者。
工作者:当领导者检测到I/O事件之后,它立即转换成工作者,对I/O事件进行处理,处理完毕之后它会转变为追随者。
如下图:
这里写图片描述
由于领导者线程自己监听I/O事件并处理客户请求,因而领导者/追随者模式不需要在线程之间传递数据。也不需要像半同步/半异步模式那样同步对请求队列的访问。但是领导者追随者的一个明显的缺点就是仅支持一个事件源集合,因而无法让每个工作线程同时管理多个客户连接。
4、领导者/追随者模式的缺点
极端情况下,当所有线程都变为工作者忙于处理客户端的请求,没有线程担任领导者的角色,此时客户端的请求会被拒绝。

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值