线程池下的三种socket模型分析

基于线程池下的三种模型分析

线程池:预先创建指定数量的线程,节省在实际应用中不断新建和回收子线程的时间。

模型1

每个线程都阻塞于accept上,当有客户端连接时,阻塞accept上的线程都被唤醒,竞争,只有一个线程去处理accept,其他线程继续阻塞。

模型2

设置一个主控线程,主控线程accept,其他任务线程等待主控线程分配任务

模型3(效率最高)

引入互斥锁,每个线程先争一把锁,谁抢到这把锁mutex,谁去accept,连接后马上释放锁,启动多一个线程,避免A线程accept后又有一个客户端马上连接。
注意:并不是每一次释放锁后,其他线程又要重新去竞争。实质上,内核实现抢锁的机制:第一次属于竞态,而后面未竞争到的线程都阻塞在pthread_mutex_lock上,并且排好队,每次释放锁后将会先优先执行队首的第一个线程。

pthread_mutex_lock(&mutex);
accept(listenfd,&client_addr,&client_addrlen);
pthread_mutex_unlock(&mutex);
...处理客户端请求...

以上三种模型在实际应用中所支持的客户端数量级差不多,但经测试模型3的性能最高,本文主要阐述模型3

==========================================================================================================

还需要思考一个问题

线程池大小在一开始已被预先固定下来,有可能会出现线程过剩线程紧缺的问题,导致应用中不灵活。

解决:

  1. 设置最大阀值max_work_num //最大线程的数量,避免无限制的创建线程导致性能下降。
  2. 设置最小阀值min_work_num //当服务量少时,提高性能
  3. 当前阀值cur_work_num //目前处于哪种状态
  4. 正在使用的线程数量this_work_num //根据此来改变阀值
  5. 线程状态STATUS //BUSY or FREE

场景分析:
当引入以上5个变量后,线程池可根据当前客户端连接的数量动态扩容或减少。(例如当前阀值为最大时,根据线程状态获取正在使用的线程数量,在根据数量来调整当前阀值该扩充还是减少,并且范围在min_work_num至max_work_num之间。)

线程扩充操作:主控线程调用pthread_create创建。
线程减少操作:主控线程调用pthread_kill发送信号来终止指定线程。

难点注意:
对于pthread_kill的操作:这里还需要作进一步讲解,我们知道线程的结束有 子线程调用pthread_exit终止自己 以及 主控线程调用pthread_cancel发送终止信号给子线程,注意pthread_cancel后系统并不会马上关闭被取消线程,只有在被取消线程下次系统调用时,才会真正结束线程,或调用pthread_testcancel,让内核去检测是否需要取消当前线程,但是如果要杀死的子线程阻塞在pthread_mutex_lock下,子线程将无法终止,同理也无法自身调用Pthread_kill终止自己,因为已经阻塞。因此引入了pthread_kill操作,该操作无须像pthread_cancel需等待下一次系统调用才能完成,还需注意线程间不共享信号屏蔽字,当线程处于空闲状态时,通过指定SIGUSR信号来设定捕捉函数,在信号捕捉函数内调用Pthread_exit终止自己,当线程处于繁忙时,设置信号屏蔽字。

通过以上分析,基本上可以动手自行设计模型3,操作有些复杂,代码部分本人后续补上,如果不足请指正,感谢!

你可能感兴趣的:(linux系统编程)