前置问答:
1.为什么要使用线程池? 避免大量创建和销毁线程,提升性能。
2.线程池主要工作流程?一是外部不断地向线程池添加任务,而是线程池内部不断地取任务执行,这是典型的生产者消费者模型。
3.线程池有几种类型?半同步半异步线程池 和 领导者追随者线程池。
第一部分:
半同步半异步线程池的工作流程:
代码实现:
1.启动:启动若干个线程,每个线程函数内部会循环从任务队列中取任务,任务队列的内容就是线程函数的函数名。
要点:
a. 线程函数是需要传给线程池对象的,线程池只负责管理线程,并不关心具体的工作线程的任务内容。
b. 刚启动线程池,没有传入任何任务时,此时线程池内的所有工作者线程处于阻塞等待状态(使用条件变量和互斥量),等待任务的到来。使用while(m_running)进行循环等待,当m_running为false时即为线程池停止服务时。
2.添加任务:向线程池申请线程执行任务,线程池对象内部会想任务队列push一个任务。
要点:
a. 向任务队列push任务时,同步队列内部会通过条件变量唤醒正在阻塞的等待任务的工作者线程。
条件变量的使用过程如下:
①. 拥有条件变量的线程获取互斥量;
②. 循环检查某个条件,如果条件不满足,则阻塞线程直到条件满足。如果条件满足,向下执行;
③. 某个线程满足条件执行完之后调用notify_one或notify_all唤醒一个或所有等待的线程;
b.任务执行结束后,工作者线程继续陷入等待状态,直到下一个任务来临。
3.停止:等待所有线程结束后停止线程池。
要点:
a. 保证停止操作只能被调用一次,需要加锁;
b. 将同步队列停止,这样同步队列就不再提供新的任务;
c. 将线程池运行状态标示m_running置为停止状态,保证工作者线程函数不再等待新任务的到来;
d. 等待所有工作者线程退出后,将线程池内创建好的线程组清空,释放资源;
关于半同步半异步线程池问答:
1.半同步半异步线程池如何构造的?主要分三层:同步服务层,任务队列,异步服务层。
2.任务队列为什么需要设置上限?同步任务队列如果不加上线控制,会导致排队任务过多,内存暴涨。
3.生产者过度生产任务时,有什么影响?任务被处理的等待时间会很长。
参考文档:
《C++11并发指南三(Lock详解)》
《四种windows多线程通信方式》
《生产者消费者问题》
《领导者跟随者模式》
《高性能IO设计模式概述》
期待下一篇:线程池的设计(二):领导者追随者线程池的设计
转帖请标明出自: