c++线程池简介

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/xiaoma_bk/article/details/102233373

1.线程池

1.1 线程池定义

  • 简单来说就是有一堆已经创建好的线程(最大数目一定),初始化时他们都处于空闲状态,当有新的任务进来时,从线程池中取出一个空闲的线程处理任务,然后当任务处理完成之后,该线程被重新放回到线程池中,供其他的任务使用,当线程池中的线程都在处理任务时,就没有空闲线程供使用,此时,若有新的任务产生,只能等待线程池中有线程结束任务空闲才能执行。

1.2 为何使用线程池

  • 性能:每开启一个新的线程都要消耗内存空间及资源(默认情况下大约1 MB的内存),同时多线程情况下操作系统必须调度可运行的线程并执行上下文切换,所以太多的线程还对性能不利。而线程池其目的是为了减少开启新线程消耗的资源(使用线程池中的空闲线程,不必再开启新线程,以及统一管理线程(线程池中的线程执行完毕后,回归到线程池内,等待新任务))。

  • 时间:无论何时启动一个线程,都需要时间(几百毫秒),用于创建新的局部变量堆,线程池预先创建了一组可回收线程,因此可以缩短过载时间。

线程池缺点:线程池的性能损耗优于线程(通过共享和回收线程的方式实现),但是:

  1. 线程池不支持线程的取消、完成、失败、通知等交互性操作。
  2. 线程池不支持线程执行的先后次序排序。
  3. 不能设置池化线程(线程池内的线程)的Name,会增加代码调试难度。
  4. 线程池通常都是后台线程,优先级为ThreadPriority.Normal。
  5. 线程池阻塞会影响性能(阻塞会使CLR错误地认为它占用了大量CPU,CLR能够检测或补偿(往池中注入更多线程),但是这可能使线程池收到后续超负荷的影响。Task解决了这个问题)。
  6. 线程池使用的是全局队列,全局队列中的线程依旧会存在竞争共享资源的情况,从而影响性能(Task使用本地队列解决了这个问题)

1.3 线程池的工作原理

  • CLR初始化时,线程池中是没有线程的。在内部,线程池维护了一个操作请求队列。应用程序执行一个异步操作时,会将一个记录项追加到线程池的队列中。线程池的代码从这个队列中读取记录将这个记录项派发给一个线程池线程。如果线程池没有线程,就创建一个新线程。当线程池线程完成工作后,线程不会被销毁,相反线程会返回线程池,在那里进入空闲状态,等待响应另一个请求,由于线程不销毁自身,所以不再产生额外的性能损耗。
  • 程序向线程池发送多条请求,线程池尝试只用这一个线程来服务所有请求,当请求速度超过线程池线程处理任务速度,就会创建额外线程,所以线程池不必创建大量线程。
  • 如果停止向线程池发送任务,池中大量空闲线程将在一段时间后自己醒来终止自己以释放资源(CLR不同版本对这个事件定义不一).

1.5 工作者线程&I/O线程

线程池允许线程在多个CPU内核上调度任务,使用多个线程能并发工作,从而高效率的使用系统资源,提升程序的吞吐性。
CLR线程池分为工作者线程与I/O线程两种:

工作者线程(workerThreads):负责管理CLR内部对象的运作,提供”运算能力“,所以通常用于计算密集(compute-bound)性操作。

I/O线程(completionPortThreads):主要用于与外部系统交换信息(如读取一个文件)和分发IOCP中的回调。

注意:线程池会预先缓存一些工作者线程因为创建新线程的代价比较昂贵。

猜你喜欢

转载自blog.csdn.net/xiaoma_bk/article/details/102233373