高效线程池之无锁化实现(Linux C)
from:http://blog.csdn.net/xhjcehust/article/details/45844901
笔者之前练手写过一个小的线程池版本(已上传至https://github.com/xhjcehust/thread-pool),最近几天复习了一下,发现大多数线程池实现都离不开锁的使用,如互斥量pthread_mutex*结合条件变量pthread_cond*。众所周知,锁的使用对于程序性能影响较大,虽然现有的pthread_mutex*在锁的申请与释放方面做了较大的优化,但仔细想想,线程池的实现是可以做到无锁化的,于是有了本文。
1.常见线程池实现原理
如上图所示,工作队列由主线程和工作者线程共享,主线程将任务放进工作队列,工作者线程从工作队列中取出任务执行。共享工作队列的操作需在互斥量的保护下安全进行,主线程将任务放进工作队列时若检测到当前待执行的工作数目小于工作者线程总数,则需使用条件变量唤醒可能处于等待状态的工作者线程。当然,还有其他地方可能也会使用到互斥量和条件变量,不再赘述。
2.无锁化线程池实现原理
为解决无锁化的问题,需要避免共享资源的竞争,因此将共享工作队列加以拆分成每工作线程一个工作队列的方式。对于主线程放入工作和工作线程取出任务的竞争问题,可以采取环形队列的方式避免。在解决了锁机制之后,就只剩下条件变量的问题了,条件变量本身即解决条件满足时的线程通信问题,而信号作为一种通信方式,可以代替之,其大体编程范式为:
- sigemptyset(&zeromask);
- sigemptyset(&newmask);
- sigaddset(&newmask, SIGXX);
- sigprocmask(SIG_BLOCK, &newmask, &oldmask) ;
- while (!CONDITION)
- sigsuspend(&zeromask);
- sigprocmask(SIG_SETMASK, &oldmask, NULL)
3.无锁化线程池具体实现
在无锁线程池中,区别于常见线程池的地方主要在于信号与条件变量、任务调度算法、增加或减少线程数目后的任务迁移,另外还有一点就是环形队列的实现参考了Linux内核中的kfifo实现。
(1) 信号与条件变量
信号与条件变量的区别主要在于条件变量的唤醒(signal)对于接收线程而言可以忽略,而在未设置信号处理函数的情况下信号的接收会导致接收线程甚至整个程序的终止,因此需要在线程池产生线程之前指定信号处理函数,这样新生的线程会继承这个信号处理函数。多线程中信号的发送主要采用pthread_kill,为避免使用其他信号,本程序中使用了SIGUSR1。
(2) 任务调度算法
常见线程池实现的任务调度主要在操作系统一级通过线程调度实现。考虑到负载均衡,主线程放入任务时应采取合适的任务调度算法将任务放入对应的工作者线程队列,本程序目前已实现Round-Robin和Least-Load算法。Round-Robin即轮询式地分配工作,Least-Load即选择当前具有最少工作的工作者线程放入。
(3) 任务迁移
在线程的动态增加和减少的过程中,同样基于负载均衡的考量,涉及到现有任务的迁移问题。由于工作队列采取环形队列的形式,任务的取出应由工作者线程完成,主线程不能实时取出工作,故在线程的动态增加时的任务迁移尚未有比较好的解决办法,只能通过线程增加后的任务调度算法实现。在线程的动态减少后,原先线程上未能执行完的任务由主线程再次根据任务调度算法重新分配至其他存活的工作者线程队列中。
(4) 环形队列
源码中环形队列实现主要参考了Linux内核中kfifo的实现,如下图所示:
队列长度为2的整次幂,out和in下标一直递增至越界后回转,其类型为unsigned int,即out指针一直追赶in指针,out和in映射至FiFo的对应下标处,其间的元素即为队列元素。
以上主要是一些方案性的说明,至于具体细节的实现有兴趣的读者可以参考https://github.com/xhjcehust/LFTPool,有问题欢迎随时联系讨论,笔者正值找工作季,求fork,求拍砖!!!
高效线程池之无锁化实现(Linux C)的更多相关文章
- (转)高效线程池之无锁化实现(Linux C)
本文链接:https://blog.csdn.net/xhjcehust/article/details/45844901 笔者之前照着通用写法练手写过一个小的线程池版本,最近几天复习了一下,发现大多 ...
- java并发包&线程池原理分析&锁的深度化
java并发包&线程池原理分析&锁的深度化 并发包 同步容器类 Vector与ArrayList区别 1.ArrayList是最常用的List实现类,内部是通过数组实现的, ...
- java无锁化编程一:目录
假设我们用netty做服务,当接受到网络传输的码流,我们通过某种手段将这种传输数据解析成了熟悉的pojo,那这些pojo该如何进一步处理? 比如游戏中的抢购.场景业务等,对处理那种高并发的业务场景,如 ...
- Java CAS同步机制 原理详解(为什么并发环境下的COUNT自增操作不安全): Atomic原子类底层用的不是传统意义的锁机制,而是无锁化的CAS机制,通过CAS机制保证多线程修改一个数值的安全性。
精彩理解: https://www.jianshu.com/p/21be831e851e ; https://blog.csdn.net/heyutao007/article/details/19 ...
- Netty源码学习系列之1-netty的串行无锁化
前言 最近趁着跟老东家提离职之后.到新公司报道之前的这段空闲时期,着力研究了一番netty框架,对其有了一些浅薄的认识,后续的几篇文章会以netty为主,将近期所学记录一二,也争取能帮未对netty有 ...
- 高效线程池(threadpool)的实现
高效线程池(threadpool)的实现 Nodejs编程是全异步的,这就意味着我们不必每次都阻塞等待该次操作的结果,而事件完成(就绪)时会主动回调通知我们.在网络编程中,一般都是基于Reactor线 ...
- linux无锁化编程--__sync_fetch_and_add系列原子操作函数
linux支持的哪些操作是具有原子特性的?知道这些东西是理解和设计无锁化编程算法的基础. 下面的东西整理自网络.先感谢大家的分享! __sync_fetch_and_add系列的命令,发现这个系列命令 ...
- 【学习】005 线程池原理分析&锁的深度化
线程池 什么是线程池 Java中的线程池是运用场景最多的并发框架,几乎所有需要异步或并发执行任务的程序 都可以使用线程池.在开发过程中,合理地使用线程池能够带来3个好处. 第一:降低资源消耗.通过重复 ...
- Nodejs事件引擎libuv源码剖析之:高效线程池(threadpool)的实现
声明:本文为原创博文,转载请注明出处. Nodejs编程是全异步的,这就意味着我们不必每次都阻塞等待该次操作的结果,而事件完成(就绪)时会主动回调通知我们.在网络编程中,一般都是基于Reactor线程 ...
随机推荐
- 关于JAVA中URL传递中文参数的问题
今天在调用一个接口时,需要传递一个中文参数,结果获取不到数据,原因就在于中文传参的编码问题. 问题来源:URL url= new URL("http://XXX?OrganName=司法厅& ...
- 查找无用代码Dead Code的一些心得
博客搬到了fresky.github.io - Dawei XU,请各位看官挪步.最新的一篇是:查找无用代码Dead Code的一些心得.
- 安装64位ubuntu 14.04-搭建android开发环境
end
- Centos7.0挂载优盘安装jdk1.7和tomcat7.0
Centos7.0挂载优盘安装jdk1.7和tomcat7.0 前言: 笔者发现用wget方法直接在服务器下载jdk和tomcat速度很慢,而且jdk1.7用wget方法下载链接不好找,不如直接从官网 ...
- EventBus3.0使用总结
在Android中,接口回调已经能够处理掉大部分业务需求了,实在太变态的需求就用广播也能够完成,自己写的性能好出问题也好解决.....工作需要,不得不看看EventBus的用法,今天就来介绍一下学习经 ...
- Android开发之位置定位详解与实例解析(GPS定位、Google网络定位,BaiduLBS(SDK)定位)
在android开发中地图和定位是很多软件不可或缺的内容,这些特色功能也给人们带来了很多方便.定位一般分为三种发方案:即GPS定位.Google网络定位以及基站定位 最简单的手机定位方式当然是通过GP ...
- nodejs创建ejs工程
<Node.js开发指南>创建ejs项目的命令为: express -t ejs microblog.执行后,创建的是jade项目.在express3.x,express4.x中创建ejs ...
- flex脚本的申明
//脚本申明的格式 <fx:Script> <![CDATA[ ]]></fx:Script> //程序完成的时候自动调用的事件 cre ...
- javascript进击(六)Jquery
引用 jQuery 如需测试 JavaScript 库,您需要在网页中引用它. 为了引用某个库,请使用 <script> 标签,其 src 属性设置为库的 URL: <!DOCTYP ...
- 简单的实现QQ通信功能(三)
第三部分:登陆界面的设计及代码 一:效果图及界面设计 1. 效果图: 2. 界面设计: (1)仿照QQ的登陆界面,右上角放了三个Label,用来做关闭.最小化和设置,使用了它们的Click事件当做按钮 ...