手写线程池与性能分析

蒸汽
蒸汽
发布于 2024-10-17 / 43 阅读
0
0

手写线程池与性能分析

池式结构

作用:将池中的thing进行统一的收发管理

种类:线程池、内存池、连接池、对象池等等

线程池

是什么

:维持和管理固定数量线程的池式结构

为什么要固定线程数量:

image-20240927072701824

维持:避免频繁创建

管理: 管理线程状态, 有任务,活跃执行, 没有任务,休眠

组成部分: 固定数量的线程 + 队列的设计

为什么用队列?: 加锁 方便使用各种力度的锁(力度则加锁执行临界资源处理所需要的时间)

有那些力度的锁?:

原子操作、自旋锁pthread_spin_lock(CPU不会切换线程,采用cpu空转的方式等待)、互斥锁pthread_mutex_lock

队列的实现:

image-20240927073756992

固定多少数量的线程?

从任务的类型出发+cpu核心数

不断测试得出:

image-20240927073936289

1.从cpu核心数开始测试+1 +1(基本在用户态执行)

2.从2倍核心数开始测试 + 1 + 1(内核用户切换执行)

为什么要两倍开始测?

image-20240927074530967

线程池如何工作

image-20240927074924873

reactor对线程的举例

image-20240927075035293

单racctor只有一个线程处理所有网络io,若同时有3个链接,第一个连接处理很大量的数据,其他的连接必须等待第一个连接完成,耗时很长

多reactor每个连接封装成一个任务,分配给一个线程,同时能处理更多的io

如何解决问题

生产消费模型:

生产者线程为抛出任务的线程

消费者线程:

消费者线程为接手任务的线程

image-20240927075622702

image-20240927075729133

异步任务:

image-20240927075909172

解决了什么问题

异步执行耗时任务,优化时间开销

技术如何在工作或开源框架中应用

image-20240927080320909

1.接口设计

用户只需要使用前三种,create, terminate, post

image-20240927081234045

2.数据结构设计

task 、task_queue、threadpool

原子变量:

image-20240927081735684

image-20240927082433242

static 来设计接口作用:

只暴露给自己不暴露给用户的接口都写成static

使得该接口只在本文件可见,在别的文件不可见,避免了命名冲突

设计思想

image-20240927084115812

回滚式编程:

创建资源时用回滚式

image-20240927084600123

防御性编程

释放资源的时候用防御性编程

image-20240927090530811

问题:为什么task_queue的head、tail指针一个是一级一个二级?

image-20240927085140578

image-20240927085948475

用二级指针可以不限定任务task类型,只要该任务的结构起始内存是一个用于链接的指针就行,这样可以支持各种task的扩展

编译动态库:

image-20240927092010034

测试:

google test工具

两个文件

taskqueue_test

threadpool_test

链接动态库

image-20240927092558142


评论