1. 一般情况下,多线程计算服务,最简单的模式如下:
上面描述的过程 就是主线程发起工作请求,Work Threads 去主线程拿到工作请求,再进行计算;
这里存在对主线程的访问加锁问题;
2. 改进后的方案:
上面的多线程计算模式可以改进一下:如( CLR Thread Pool V4中采用的方案)
每个线程上再开一个队列:
上面的过程就是有任务就先往Global Queue里放,然后,再分发到工作线程中,这个过程不需要加锁,直接分配任务,当新的工作请求过来时,就直接加到Worker Thread 1的队列里等待处理;
但是上面的有一个问题,如果Worker Thread 2 完成了Task1的情况下,他的下一个工作任务如何获取呢?
请看上图,先从其它Worker Thread的队列中Stealing一个工作任务过来;
特别注意一个优化策略,就是如果 Worker Thread1 当前正在计算的任务如果触发了新的任务,这个时候,任务的请求是直接加到Worker Thread1 的工作队列的底部,优先等待被调度; (这个是对性能优化是有好处的,相关的数据应该都还在CPU的高速缓冲区中存在);
3. 无锁化的线程池的原理
将共享工作队列加以拆分成每工作线程一个工作队列的方式。对于主线程放入工作和工作线程取出任务的竞争问题,可以采取环形队列的方式避免,计算任务的触发采用条件变理及信号,而任务调度需要采用合适的调度算法:如 Round-Robin和Least-Load算法, Round-Robin即轮询式地分配工作,Least-Load即选择当前具有最少工作的工作者线程放入;
任务环形队列:
上面的算法过程就是不停的移动Out指针,去追敢In 指针的位置,不需要加锁;
参考:
http://www.danielmoth.com/Blog/New-And-Improved-CLR-4-Thread-Pool-Engine.aspx
https://blog.csdn.net/xhjcehust/article/details/45844901