陈硕的Blog

发布一个 Linux 下的 C++ 多线程库

发布一个我自己业余时间编写的 C++ 多线程库 for Linux,这个库只有不到 1000 行源代码,封装了 pthreads 的常用功能(互斥器、条件变量、线程),实现了简单的线程池,并仿照 java concurrent 包编写了 BlockingQueue 和 CountDownLatch。库里的每个 class 都提供了使用样例。

这个库的内容:

  • 整数的原子操作, AtomicInt32 和 AtomicInt64
  • 线程,Thread
  • 线程池,ThreadPool
  • 互斥器与条件变量, MutexLock,MutexLockGuard 与 Condition
  • 带调用栈信息 (stack trace) 的异常基类,Exception
  • 仿 Java concurrent 的 BlockingQueue 和 CountDownLatch
  • Singleton 与 ThreadLocal

注:我故意没有提供信号量 Semaphore 的封装。将来或许会增加读写锁的封装,如果我在博客中用到的话。

Thread 和 ThreadPool 的接口设计采用了《以 boost::function 和 boost:bind 取代虚函数》里提倡的风格,没有使用继承和基类。

注意,CurrentThread 有一个 thread local 变量 t_threadName,其作用是在调试和分析 core dump 时打印线程的名称,例如:

(gdb) p 'muduo::CurrentThread::t_threadName'
$4 = 0x4057fe "ThreadPool2"

MutexLock,MutexLockGuard 与 Condition 的使用请参考《多线程服务器的常用编程模型》。

CountDownLatch 的使用样例见 test/BlockingQueue_test.cc

git 下载地址: http://github.com/chenshuo/recipes

浏览源代码: http://github.com/chenshuo/recipes/tree/master/thread/

这个库在 Debian Squeeze 和 Ubuntu 10.04 LTS 下编译测试通过,适用于 x86 和 x86-64 平台。

posted on 2010-08-21 23:47 陈硕 阅读(9697) 评论(37)  编辑 收藏 引用

评论

# re: 发布一个 Linux 下的 C++ 多线程库 2010-08-22 07:11 chaogu

@bslz
我觉得蛮好。  回复  更多评论   

# re: 发布一个 Linux 下的 C++ 多线程库 2010-08-22 07:35 三窍门

感觉还不错  回复  更多评论   

# re: 发布一个 Linux 下的 C++ 多线程库 2010-08-22 12:25 ccsdu2009

@bslz
这是个人爱好与你有关吗?  回复  更多评论   

# re: 发布一个 Linux 下的 C++ 多线程库 2010-08-22 23:30 evoup

首先开源精神可嘉,但是就我所知linux下几个著名的服务器都压根不用posix线程,有点郁闷。  回复  更多评论   

# re: 发布一个 Linux 下的 C++ 多线程库 2010-08-23 09:27 arrow8209

@bslz
虽然是在重复造轮子,但是轮子不是谁都会制造的,如果自己没有制造过只知道使用,怎么可以提高。造轮子是一个学习的过程,是一个成长的工作,一个好的程序员都应该重复制造过轮子,只是自己不知道而已。  回复  更多评论   

# re: 发布一个 Linux 下的 C++ 多线程库 2010-08-23 10:22 arthurlee

继续努力!  回复  更多评论   

# re: 发布一个 Linux 下的 C++ 多线程库 2010-08-23 13:07 匿了

上午看到,想谴责bslz几句.
刚看了下封装, 客观的说, 的确很垃圾, 而且是非常垃圾.  回复  更多评论   

# re: 发布一个 Linux 下的 C++ 多线程库 2010-08-23 20:55 杨粼波

我就用的POSIX的,用POSIX的还好吧……

LZ虽然封装得不是很好,不过至少也是一个学习过程。  回复  更多评论   

# re: 发布一个 Linux 下的 C++ 多线程库 2010-08-24 07:11 chaogu

@bslz
第一:楼主不傻逼,写出这东西的不是傻逼能做到的,要不你试试。
第二:楼主也不是沾沾自喜,因为好的程序员就是应该这样,喜欢上编程,并向人展示自己的成果,甚至炫耀都无可厚非。
第三:造轮子不是什么丢人的事情,而且伟大的东西都是从轮子开始的,比如Linux。
第四:造轮子的不是傻逼,骂造轮子的人才傻逼,因为你没资格。
第五:发首页没有污染视听一说,园子就是给人撒种子的。
第六:楼主的东西没有污染视听,好东西怎么会污染视听。  回复  更多评论   

# re: 发布一个 Linux 下的 C++ 多线程库 2010-08-24 08:30 ccsdu2009

@chaogu
顶  回复  更多评论   

# re: 发布一个 Linux 下的 C++ 多线程库 2010-08-24 22:17 jigsaw

看了下代码,看起来像c++/c初学者练手的习作。这话难听,但我自认没有带任何成见。楼主应该知道我是哪颗葱吧。  回复  更多评论   

# re: 发布一个 Linux 下的 C++ 多线程库[未登录] 2010-08-25 00:11 kk

其他不说了,看到c++程序里面包含<stdio.h>使用一堆printf,sprintf的就烦,喜欢用boost但不喜欢OO又要封装这封装那,真不知道博主喜欢c++还是讨厌c++。  回复  更多评论   

# re: 发布一个 Linux 下的 C++ 多线程库 2010-08-25 08:55 陈硕

@kk
用 snprintf 是为了避免在堆上分配内存,ostringstream 则正好相反;在多线程程序里,内存分配可能会加锁,用栈上的缓冲区能避免无谓的加锁。
用 fprintf 是因为它是线程安全的,cout/cerr 则相反。cerr << a << b; 是两次函数调用,中间可能会被打断进行上下文切换,造成输出内容不连续,插入了其他字符。而 fprintf(stderr, "%s %d", a, b); 是一次函数调用,而且是线程安全的,打印的内容不会受其他线程影响。
另外我没有见过谁在产品代码里用 iostream。  回复  更多评论   

# re: 发布一个 Linux 下的 C++ 多线程库 2010-08-25 18:43 大渊献

看了“chaogu ”的三流学校,专门来拜此贴。发现其实还是挺和谐的嘛。有人言词犀利,估计是习惯了吧。

printf我也用,特别在UNICODE下想输出中文的时候。  回复  更多评论   

# re: 发布一个 Linux 下的 C++ 多线程库 2010-08-27 00:57 evoup

@陈硕
受教了!  回复  更多评论   

# re: 发布一个 Linux 下的 C++ 多线程库 2010-08-27 01:44 trueOO

特来参观此贴^_^
@kk
这方面楼主没问题的,google的C++编程规范基本上也不提倡用流
下了代码仔细看了,说实话楼主别介意啊,也难怪有素质修养不高的喷子骂人了。  回复  更多评论   

# re: 发布一个 Linux 下的 C++ 多线程库[未登录] 2010-08-29 04:42 杨粼波

boost::function和boost::bind的使用也是有代价的,
所以,在设计的时候,需要仔细的考量。

vptr虽然也有代价,也不能说一棒子打死的,虽然继承会产生隐性的耦合,不过在很多场景里面,它是具有它的存在的价值的。

耦合,也并非全然是坏事情。“低耦合”并非是“没耦合”。
接口,就是创建了一个限制,一个规则。人类社会中,人类不可能脱离限制,脱离规则,那么就是一个混乱的世界。同样,程序的世界也不可能说没有限制,没有规则。

Runnable的设计实际上是非常合理的设计,意图明显,结构清晰。
在一个复杂的项目里面,结构清晰,意图明显,那真是再好不过的东西了。  回复  更多评论   

# re: 发布一个 Linux 下的 C++ 多线程库 2010-08-29 17:55 Tanky Woo

朋友你好:
C/C++和算法论坛:C++奋斗乐园
欢迎你加入。
里面有C/C++交流,求助,源码,
算法学习,求助,
ACM刷题
等各种板块,
相信大家在一起能学习快乐。

论坛地址:
[url=http://www.cppleyuan.com/index.php">http://www.cppleyuan.com/index.php]http://www.cppleyuan.com/index.php">http://www.cppleyuan.com/index.php[/url]

另外,论坛现在招收版主,有意愿的朋友可以看看:
[url=http://www.cppleyuan.com/forumdisplay.php?fid=44">http://www.cppleyuan.com/forumdisplay.php?fid=44]http://www.cppleyuan.com/forumdisplay.php?fid=44">http://www.cppleyuan.com/forumdisplay.php?fid=44[/url]

注:此留言绝不是广告,只是 看见博主也是C/C++和算法的爱好者,我们想邀请博主一起加入我们的论坛。

我也是一名C/C++和ACM爱好者,大家可以去我博客看看就知道了:
[url=http://www.wutianqi.com/">http://www.wutianqi.com/]http://www.wutianqi.com/">http://www.wutianqi.com/[/url]

打扰之处请见谅。
  回复  更多评论   

# re: 发布一个 Linux 下的 C++ 多线程库 2012-06-29 12:25 杨军

atexit:
按照ISO C的规定,一个进程可以登记多达32个函数

Singleton中的析构函数用atexit,是不是有问题啊  回复  更多评论   

# re: 发布一个 Linux 下的 C++ 多线程库 2012-06-29 13:21 Solstice

@杨军
一个程序如果用到了30来个Singleton,说明本身有大问题。  回复  更多评论   

# re: 发布一个 Linux 下的 C++ 多线程库 2012-07-01 19:25 杨军

@Solstice
大哥,开发游戏过程中,业务逻辑层很容易达到30多个Singleton的,我个人觉得这个atexit函数可以不要,没有,交给我们自己来主动销毁,反而如果多了一个在这里会误导  回复  更多评论   

# re: 发布一个 Linux 下的 C++ 多线程库 2012-07-01 20:50 Solstice

@杨军
那就不要用 Singleton,直接用全局对象,在main里初始化不就行了?  回复  更多评论   

# re: 发布一个 Linux 下的 C++ 多线程库 2012-07-01 22:13 杨军

这样能解决,我查过atexit知道还好,就怕团队的其他人用错Singleton,所以我的建议是干脆别提供,让我们自己销毁,对了,问你一个弱智问题,你开发C++用的是什么工具,vi,还是其他,因为我原来是搞c#的,现在不知道用什么开发工具好,麻烦了啊  回复  更多评论   

# re: 发布一个 Linux 下的 C++ 多线程库 2012-07-02 16:14 杨军

提个bug,ProcessInfo.cc中的scanDir函数中namelist没有释放  回复  更多评论   

# re: 发布一个 Linux 下的 C++ 多线程库 2012-07-02 18:59 陈硕

@杨军
assert(namelist == NULL);
不需要释放。  回复  更多评论   

# re: 发布一个 Linux 下的 C++ 多线程库 2012-07-02 19:05 陈硕

@杨军
我测过,atexit() 处理500个Singleton没有问题。
sysconf(_SC_ATEXIT_MAX) 的返回值足够大。  回复  更多评论   

# re: 发布一个 Linux 下的 C++ 多线程库 2012-07-03 09:15 杨军

@陈硕
ok,我的错,麻烦了  回复  更多评论   

# re: 发布一个 Linux 下的 C++ 多线程库 2012-07-03 11:19 杨军

@陈硕
这次看清楚taskDirFilter,这段代码太精巧了,牛逼

你开发C++用的是什么工具,vi,还是其他  回复  更多评论   

# re: 发布一个 Linux 下的 C++ 多线程库 2012-07-03 22:45 杨军

不过我看你代码,发现你很喜欢用线程局部存储,
比如ProcessInfo的实现中
__thread std::vector<pid_t>* t_pids = NULL;
__thread int t_numOpenedFiles = 0;

这两个其实可以不用线程局部存储来实现,TLS书上的建议是最好不要大量使用,
不知道你是不是有特殊用处?  回复  更多评论   

# re: 发布一个 Linux 下的 C++ 多线程库 2012-07-03 22:52 陈硕

@杨军
For thread safety.  回复  更多评论   

# re: 发布一个 Linux 下的 C++ 多线程库 2012-07-03 23:33 杨军

@陈硕
普通函数内的栈变量,同样能过实现统计文件数,而且也是线程安全的啊  回复  更多评论   

# re: 发布一个 Linux 下的 C++ 多线程库 2012-07-04 06:40 陈硕

@杨军
写一个来看看?  回复  更多评论   

# re: 发布一个 Linux 下的 C++ 多线程库 2012-07-04 11:04 杨军

@陈硕
我写了一个

void getTids(std::vector<pid_t>& verPid){
struct dirent ** namelist=NULL;
int n=::scandir("/proc/self/task",&namelist,0,alphasort);
if(n<0){
return;
}
while(n--){
if(::isdigit(namelist[n]->d_name[0])){
verPid.push_back(atoi(namelist[n]->d_name));
}
}
}


调用的时候
std::vector < pid_t > result;
getTids(result);


都用的是函数局部变量,应该是线程安全的  回复  更多评论   

# re: 发布一个 Linux 下的 C++ 多线程库 2012-07-04 11:12 陈硕

@杨军
1. namelist 没有释放。
2. 每次调用都要分配释放内存,增加开销。  回复  更多评论   

# re: 发布一个 Linux 下的 C++ 多线程库 2012-07-04 12:11 杨军

@陈硕
是有这个问题,我改了,这段代码就是没有用TLS来实现ProcessInfo中获取线程列表功能,但就获取线程列表这种不是很频繁的操作来说,这点开销应该还行吧


void getTids(std::vector<pid_t>& verPid){
struct dirent ** namelist=NULL;
int n=::scandir("/proc/self/task",&namelist,0,alphasort);
if(n<0){
return;
}
while(n--){
if(::isdigit(namelist[n]->d_name[0])){
verPid.push_back(atoi(namelist[n]->d_name));
free(namelist[n]);
}
free(namelist);
}
}
  回复  更多评论   

# re: 发布一个 Linux 下的 C++ 多线程库 2012-07-04 13:15 陈硕

@杨军
每次调用多了N+1次内存分配和释放的开销,好处是什么?节约了一个 tls 变量?
你要认为这是值得的,那就这样写呗。  回复  更多评论   

# re: 发布一个 Linux 下的 C++ 多线程库 2012-07-04 13:30 杨军

@陈硕
但是用tls变量的写法中
int taskDirFilter(const struct dirent* d)

每次都要调用这个方法,这个方法中的dirent也是需要内存分配和释放吧  回复  更多评论   


只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   博问   Chat2DB   管理


<2010年8月>
25262728293031
1234567
891011121314
15161718192021
22232425262728
2930311234

导航

统计

常用链接

随笔分类

随笔档案

相册

搜索

最新评论

阅读排行榜

评论排行榜