两种高效的并发模式

并发编程的目的就是让程序“同时”执行多个任务。如果程序是计算密集型的,并发编程并没有优势,反而由于任务的切换使效率降低。但是对于I/O密集型(比如经常读写文件、访问数据库等),I/O操作速度远远低于CPU计算速度。如果程序阻塞在I/O操作会浪费CPU时间,如果是执行多个线程,阻塞的执行线程会主动放弃CPU(或由操作系统调度 ),将执行权转移到其他线程,由此大大提高CPU的利用率;实现上主要有多进程和多线程两种方式;并发模式是指I/O处理单元和多个逻辑处理单元之间协调完成任务的方法。

  • 半同步/半异步模式

1. I/O模型中的同步和异步区分是向应用程序通知是何种I/O事件(就绪还是完成),以及由谁来完成

 I/O读写(程序还是内核)。

2. 并发模式中的同步和异步:同步指的是程序完全按照代码序列的顺序执行;异步指的是程序的执行需要由系统事件来驱动。常见的系统事件包括中段、信号等。

同步线程:按照同步方式运行的线程---------------执行效率高,实时性强(多被嵌入式程序采用)

                                                                            编写复杂,难于调试和扩展,不适合于大量的并发

异步线程:按照异步方式运行的线程----------------执行效率低,实时性差

                                                                              逻辑简单

服务器既要求实时性,又要求能同时处理多个客户请求的应用程序就应该使用半同步/半异步模式实现。同步线程用来处理客户业务逻辑(业务逻辑单元),异步线程用来处理I/O事件(I/O处理单元)。异步线程监听到客户请求后,将其封装成请求对象并插入请求队列中。请求队列将通知某个工作在同步模式下的工作线程来读取并处理该请求对象。

在服务器程序中,半同步半异步模式一般结合两种高效的事件处理模式和几种I/O模型使用,于是就有了许多变体:

(1)半同步/半反应堆模式

  • 异步线程由主线程充当,负责监听所有的socket上的事件;
  • 监听的socket上有可读事件发生(新的连接请求),主线程接受连接获得连接的socket,往epoll内核事件表注册该socket上的读事件(有新的客户请求到来或者有数据要发送到客户端);
  • 主线程将该连接的socket插入到请求队列中(所有的工作线程都睡眠在请求队列上,有任务到来,他们通过特定规则获得任务的执行权),只有空闲的工作线程才可能获取任务;

 缺点:

  • 主线程向请求队列添加任务和工作线程从请求队列里获取任务都要对请求队列加锁,消耗大量CPU时间;
  • 一个工作线程同一时间只能处理一个客户请求,当客户请求量大而工作线程有限,会造成任务对象堆积;如果靠增加工作线程数量来解决问题,线程切换也会消耗大量CPU时间。

(2)高效的半同步/半异步模式:一个工作线程能处理多个客户请求

  • 主线程只负责监听socket,连接socket由工作线程管理,有新的连接请求到来时主线程接收连接并将对应的socket分派(最简单的分派方式就是主线程和工作线程之间建立管道)给某个工作线程;
  • socket上的任何I/O操作都由该工作线程来处理,直到客户端关闭连接;’
  • 工作线程检测到有新的客户连接请求就把该新的socket上的读写事件注册到自己的epoll内核事件表中;
  • 每个线程都维护着自己的循环,各自独立的监听不同的事件,每个线程都工作在异步模式,所以该模式严格行来说又并非半同步半异步模式。
  • 领导者/追随者模式

1.  该模式是多个工作线程轮流获得事件源集合,轮流监听、分发并处理事件。无需管道进行主线程和工作线程之间的交流,也无需对消息对列进行访问。

  • 在任意时间点,程序仅有一个领导者线程,它负责监听I/O事件而其他线程则成为追随者,同时也休眠在线程池中等待成为新的领导者。
  • 当前的领导者如果检测到I/O事件,首先要从线程池中推选出新的领导者线程处理I/O事件;
  • 找到新的领导者之后,旧的领导者线程就处理I/O事件(处理完新的领导者才正式诞生),新的领导者等待下一次I/O事件的到来;
  • 主线程和工作线程实现了并发

(1)句柄Handle:用于表示I/O事件源,linux下就是一个文件描述符;句柄集管理众多句柄,使用wait_for_event方法来监听这些句柄上的I/O事件,并将就绪事件通知给领导者线程。领导者调用绑定(register_handle方法)到Handle上的事件处理器来处理事件。

(2)线程集:所有工作线程的管理者,负责线程同步和新的领导者的推选;其中的线程任意时间必然处于三种状态之一(leader、processing、follower)

(3) 事件处理器(使用前已经和句柄绑定)和具体的事件处理器

  • 事件处理器通常包括一个或多个回调函数handle_event用于处理时间对应的业务逻辑;
  • 具体的事件处理是具体的时间处理器(事件处理器的派生类----------重新实现handle_event方法处理特定的任务)

(4)缺点: 单一事件源,无法让每个工作线程管理多个客户连接。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值