池式结构
作用:将池中的thing进行统一的收发管理
种类:线程池、内存池、连接池、对象池等等
线程池
是什么
:维持和管理固定数量线程的池式结构
为什么要固定线程数量:
维持:避免频繁创建
管理: 管理线程状态, 有任务,活跃执行, 没有任务,休眠
组成部分: 固定数量的线程 + 队列的设计
为什么用队列?: 加锁 方便使用各种力度的锁(力度则加锁执行临界资源处理所需要的时间)
有那些力度的锁?:
原子操作、自旋锁pthread_spin_lock(CPU不会切换线程,采用cpu空转的方式等待)、互斥锁pthread_mutex_lock
队列的实现:
固定多少数量的线程?
从任务的类型出发+cpu核心数
不断测试得出:
1.从cpu核心数开始测试+1 +1(基本在用户态执行)
2.从2倍核心数开始测试 + 1 + 1(内核用户切换执行)
为什么要两倍开始测?
线程池如何工作
reactor对线程的举例
单racctor只有一个线程处理所有网络io,若同时有3个链接,第一个连接处理很大量的数据,其他的连接必须等待第一个连接完成,耗时很长
多reactor每个连接封装成一个任务,分配给一个线程,同时能处理更多的io
如何解决问题
生产消费模型:
生产者线程为抛出任务的线程
消费者线程:
消费者线程为接手任务的线程
异步任务:
解决了什么问题
异步执行耗时任务,优化时间开销
技术如何在工作或开源框架中应用
1.接口设计
用户只需要使用前三种,create, terminate, post
2.数据结构设计
task 、task_queue、threadpool
原子变量:
static 来设计接口作用:
只暴露给自己不暴露给用户的接口都写成static
使得该接口只在本文件可见,在别的文件不可见,避免了命名冲突
设计思想:
回滚式编程:
创建资源时用回滚式
防御性编程
释放资源的时候用防御性编程
问题:为什么task_queue的head、tail指针一个是一级一个二级?
用二级指针可以不限定任务task类型,只要该任务的结构起始内存是一个用于链接的指针就行,这样可以支持各种task的扩展
编译动态库:
测试:
google test工具
两个文件
taskqueue_test
threadpool_test
链接动态库