线程池:线程管理
线程池中的线程由两类组成:工作者线程和I/O线程。
ThreadPool.QueueUserWorkItem和Timer类总是将工作项(即线程要回调的委托)放到全局队列中。工作者线程采用一个FIFO算法将工作项从这个队列中取出,并处理它们。由于多个工作者线程可能同时从全局队列中拿走工作项,所以所有的工作者线程都竞争一个线程同步锁,以保证两个或者多个线程不会获取同一个工作项。
对于默认的TaskScheduler调度Task对象时,如果是一个非工作者线程调用一个Task,那么Task会添加到全局队列中。但是,每个工作者线程都有它自己的本地队列。当一个工作者线程调度一个Task时,Task会添加到调用线程的本地队列。
一个工作者线程准备好处理一个工作项时,它总是先检查它本地队列来查找一个Task。如果存在一个Task,工作者线程就从它本地队列中移除Task,并对工作项进行处理。工作者线程采用LIFO算法将任务从它的本地队列中取出。由于工作者线程是唯一允许访问它自己的本地队列头的线程,所以无需同步锁。
如果一个工作者线程发现它的本地队列空了,工作者线程会尝试从另一个工作者线程的本地队列中取一个Task。这个Task是从一个本地队列的尾部取走的,并要求获取一个线程同步锁,如果本地队列都变空,那么工作者线程会使用FIFO从全局队列中获取一个工作项。如果全局队列也为空,那么工作者线程把自己置入睡眠状态,等待事情的发生。如果睡眠时间太长了,它会自己醒来,并自身销毁,允许系统回收线程使用的资源(包括内核对象、栈、TEB等)。