线程模式HS/HA和L/F的区别, HS/HA的实现原理图

时间:2023-12-29 18:29:08

线程池模式一般分为两种:L/F领导者与跟随者模式、HS/HA半同步/半异步模式。 
HS/HA 半同步/ 半异步模式 :分为三层,同步层、队列层、异步层,又称为生产者消费者模式,主线程处理I/O事件并解析然后再往队列丢数据,然后消费者读出数据进行应用逻辑处理;
优点:简化编程将低层的异步I/O和高层同步应用服务分离,且没有降低低层服务性能。集中层间通信。 
缺点:需要线程间传输数据,因此而带来的动态内存分配,数据拷贝,语境切换带来开销。高层服务不可能从底层异步服务效率中获益。 
L/F 领导者跟随者模式 :在LF线程池中,线程可处在3种线程状态之一: leader、follower或processor。处于leader状态的线程负责监听tb网络端口,当有消息到达时,该线程负责消息分离,并从处于 follower状态中的线程中按照某种机制如FIFO或基于优先级等选出一个来当新的leader,然后将自己设置为processor状态去分配和处 理该事件。处理完毕后线程将自身的状态设置为follower状态去等待重新成为leader。在整个线程池中同一时刻只有一个线程可以处于leader 状态,这保证了同一事件不会被多个线程重复处理。 
缺点:实现复杂性和缺乏灵活性; 
优点:增强了CPU高速缓存相似性,消除了动态内存分配和线程间的数据交换。 
两种模式性能分析: 
L/F模式处理一个消息的时间为多路分离、分配、处理的时间,加上线程管理时间,LF中多个线程共享一个事件源,所以,需要协调它们间的行为,即 有同步开销,L/F同步开销仅为申请/释放锁的开销,在LF处理请求过程中并不需要线程上下文切换,但是在线程由follower成为leader时需要 进行线程上下文切换,所以当两个请求同时到达时,这种上下文切换会影响第二个请求的处理时间,也会带来一定的上下文开销。 
T(L/F)=T(多路分离)+T(分配)+T(处理)+T(同步)+T(上下文) 
HS/HA模式监听线程和工作线程间通过一个消息队列来交换数据。这会带来数据传递开销,。同时,监听线程和工作线程都需要去访问消息队列,造成 了资源的竞争,需要额外的同步机制来协调他们的行为,包括监听线程获取和释放资源锁,对应的工作线程获取和释放资源锁,以及监听线程在将一个请求放入队列 后通知工作线程带来的开销,我们称此为同步开销,HS/HA模式的同步开销大于L/F的同步开销,。一个请求由监听线程负责放入消息队列,但是却由工作线 程来处理,所以,每个请求都会造成一次线程上下文切 
换,由此带来的开销我们称为上下文开销。 
       T (H/H)=T(多路分离)+T(分配)+T(处理)+T(同步)+T(数据传递)+T(上下文) 
从上面分析可以看出没有并发情况下L/F模式线程池模式性能优于HS/HA模式。 
并发性能分析: 
T(多路分离)、T(分配):LF和HH中把每一个消息的到来当作一个事件来处理。tbw事件分配所做的工作是在一个事件处理器注册表中为一个事件查找 事件处理器。这一步骤花费的时间随着当前注册的事件处理器的个数变化。当线程池接受用户连接请求后会为每一个连接注册一个事件处理器,所有通过该连接发来 的请求都将由同一个事件处理器来处理。而事件处理器表采用一个平衡二叉树来实现。因此,事件分配的时间可以认为是随着并发用户数的增大而增大; 
T(处理)处理消息和管理线程所需的时间都不受并发用户数的影响。 
T(线程管理),多线程带来的线程管理开销只会随着线程池中线程数而变化,相对固定。 
LF和HH的吞吐量会随着并发用户数的增加而增加。当并发用户数达到一定数量时,CPU成为系统瓶颈,此后增大并发用户数不仅不能增加并发处理的请求个数,反而会加大多路分离和分配的时间,从而使得系统吞吐量下降。

最佳性能时线程线: 
随着线程数的增多吞吐量不断增大,当达到最大值后有一个短暂的保持阶段,此后继续增大线程数反而会使得吞吐量减小。而且当请求类型为计算密集型时线程数对 
HH 的吞吐量的影响并不是很明显。原因是HH线程池在增加线程数时线程管理开销也有较大幅度的增加。因此,通过增大线程数来改善系统性能对HH来说并不是一种有效的方法。

 非线程池下,HS/HA模式更实用

以上讨论的是使用线程池的情况下,两种模式的性能分析:

但线程池一般使用在处理小任务计算,线程数量较多,需要频繁创建和退出的情况下,对于那些线程数量固定,每个线程功能明确的情况下,就不需要使用线程池。

对于这宗情况,比如线程数量固定,一个线程负责接收分发,几个线程负责处理不同的逻辑,使用HS/HA模式不仅简单,而且更实用。

HS/HA的实现图如下:

线程模式HS/HA和L/F的区别, HS/HA的实现原理图

上图中,线程A,B,C可以分别负责不同的逻辑功能

只要线程A,B,C一直运行,那么就不需要用到线程池,使用HS/HA模式实现肯定更容易。

原文参考:http://www.cppblog.com/tbwshc/archive/2013/06/18/201124.html