秋招日记(四)线程池实现表达
学习记录
- 《深入理解计算机系统》
- 第9章 虚拟内存
- 第10章 系统I/O
- 第11章 网络编程
- 第12章 并发编程
我的面试问题解答
-
线程池实现的一段话描述
(PS:我这个线程池的实现是参考(CV)文章后面的github项目,这里的实现描述也是我自己的理解)
线程池的核心思想就是维护一个线程容器和一个任务容器,我的线程池实现的本质是所有线程共享一个线程安全的任务队列,并在此基础上实现一个简单的生产者消费者模型。在我的实现中我创建了一个function<void>类型的队列用来保存需要被执行的任务,让后将这个队列和一个互斥锁、一个条件变量以及一个布尔变量打包成一个结构体,其中互斥锁用来保护任务队列的线程安全、条件变量用来阻塞线程使线程处于空闲状态或通知线程处理任务,布尔变量用来关闭线程。
然后我使用了一个shared_ptr指针来管理一个任务队列结构体对象
在创建线程池时,我使用std::thread来动态创建线程。创建线程时,我将持有任务队列的shared_ptr指针传入每个线程中,使得所有线程都能拥有工作队列的所有权
每个线程的主体都是一个无限循环,循环中通过判断shared_ptr指向的任务队列是否为空,来确定是否需要执行任务,当任务队列为空时,线程会被任务队列结构体中的条件变量阻塞,当任务列表不为空时,线程取出任务并执行。
-
线程池实现
- 线程池是什么?
- 线程池是一组预实例化的空闲线程,它们随时可以被分配工作。
- 当需要完成大量短任务而不是少量长任务时,它们比为每个任务实例化新线程更可取。这可以避免多次创建线程的开销。
- 实现一个线程池的要求
- 一种创建线程并将它们保持在空闲状态的方法。
- 存储已创建线程的容器,如队列或任何其他能够将线程添加到池中并取出一个线程的结构。
- 保存需要处理的任务的容器
- 线程工作时使用的标准接口或抽象类。
- 线程池的工作流程
- 创建一组线程,并将创建的线程放入线程池中
- 当线程池被传递一个Task时,它从容器中获取一个线程(或者在容器为空时等待一个可用的线程),传递给它一个Task
- 一旦执行完成,线程将自己交还给池,将其放入容器中以供重用,然后阻塞自身,使自己处于睡眠状态,直到循环重复。
- 线程池的具体实现
- 线程池的成员
- 一个线程池结构体
- 一个互斥锁 std::mutex, 用来保护工作队列的线程安全
- 一个条件变量 std::condition_variable,阻塞线程让线程保持在空闲状态
- 一个布尔变量 bool isClosed,用来关闭线程
- 一个function类型的队列 std::queue<std::function<void()>>,用来存放等待执行的任务
- 一个持有线程池结构体对象的shared_ptr
- 一个线程池结构体
- 线程池的初始化
- 使用std::thread循环创建线程,创建后及时分离线程(detach)
- 线程内部是一个无限循环,当没有任务需要处理时,线程被条件变量阻塞
- 每个线程都持有线程池结构体对象的shared_ptr指针,通过该指针,线程可以从任务队列中取出任务并执行
- 线程池的析构
- 将线程池结构体中的布尔变量值置为false,并使用条件变量通知所有线程,线程被唤醒后退出无限循环
- 任务的存放与取出
- 使用std::forward将任务完美转移到工作队列中
- 使用条件变量通知一个线程处理
- 线程池的成员
- 线程池是什么?