高效并发模式--半同步/半异步模式
并发编程的目的是让程序“同时”执行多个任务。若程序是计算密集型的,并发编程并没有优势,相反由于任务的切换使得效率降低。但如果程序是I/O密集型的,比如经常读写文件,访问数据库等,则情况不同。由于I/O操作的速度远没有CPU计算的速度快,所以当程序阻塞于I/O操作将浪费大量CPU时间。
并发模式是指I/O处理单元和多个逻辑单元之间的协调完成任务的方法。
并发模式中,“同步”指的是程序完全按照代码序列的顺序执行;“异步”指的是程序的执行需要由系统事件来驱动。
以异步线程执行的程序相对复杂,难于调适和扩展,并且不适合于大量的并发。同步线程则相反,程序效率相对较低,实时性较差,但逻辑简单。
半同步/半异步模式
同步线程用于处理客户逻辑,相当于逻辑单元;异步线程用于处理I/O事件,相当于I/O处理单元。
![半同步半异步模式工作流程.png](https://i.loli.net/2020/12/21/uP2neT3l7QIZaUF.png)
半同步/半反应堆模式
half-sync / half-reactive
事件处理模式是Reactor模式:要求工作线程自己从socket上读取客户请求和往socket写入服务器应答。
![半同步-半反应堆模式.png](https://i.loli.net/2020/12/21/gcyLzCZjOGFfid4.png)
主线程:异步线程。负责监听所有 socket 上的事件。
- 当有新的连接请求到来,主线程接受连接请求得到新的连接socket,然后往epoll内核事件表中注册socket上的读写事件。
- 有新的已连接客户端请求到来或有数据要发送至客户端,主线程将该连接socket插入请求队列。
工作线程:同步线程。所有的工作线程都休眠在请求队列上,当有任务到来,它们通过竞争获得任务的接管权。
缺点:
- 主线程和工作线程共享请求队列:主线程添加任务,工作线程取出任务,都需要对请求队列加锁保护,耗费CPU时间。
- 每个工作线程在同一时间只能处理一个客户请求:若客户较多,工作线程较少,则请求队列中任务堆积,客户端响应慢。若增加工作线程,线程切换耗费大量CPU时间。
相对高效的半同步/半异步模式
每个线程都是异步线程,故并非严格意义上的半同步/半异步模式。
![高效的半同步-半异步模式.png](https://i.loli.net/2020/12/21/i6BpGWfeAcVD4YU.png)
主线程:异步线程。只负责管理监听socket(listen_socket)。当有新的连接请求到来,主线程接受连接请求得到新的连接socket,并将新返回的连接socket派发给某个工作线程。
工作线程:异步线程。负责管理请求socket(connected_socket)。主线程向工作线程派发新的连接socket后,工作线程负责该socket的任何I/O操作,直到客户端关闭。
参考:《Linux高性能服务器编程》 游双