急救:pthread多线程问题。

LiquidX 2009-03-18 09:51:19
加精
我有一个线程池, 通过信号来唤醒指定的线程开始工作, 但我发现经常有频率的pthread_cond_signal( &cond );会不能及时的唤醒一个线程, 而导致闲置线程进入繁忙状态后却没有醒过来工作, 导致了大量的繁忙线程增加, 直接导致线程池效率降低。

void addTask(): 添加一个任务后大概是这样的
TPThread* tptd = ***
printf( "sendCondSignal-start.%u\n", tptd->getID() );
tptd->sendCondSignal() //pthread_cond_signal( &cond );
printf( "sendCondSignal-end.%u\n", tptd->getID() );


static thread_function(arg): 线程函数大概这样
TPThread* tptd = arg;
while(1)
{
pthread_cond_wait( &tptd->cond, &tptd->mutex );
printf( "onWaitCondSignal.%u\n", pthread_self() );


处理任务....
}











调试信息:
正常情况下是这样的
sendCondSignal-start.3065138064
onWaitCondSignal.3065138064
sendCondSignal-end.3065138064
>>-------->currFree:31, currThreadCount:32, busy:[1]
sendCondSignal-start.2991709072
onWaitCondSignal.2991709072
sendCondSignal-end.2991709072
>>-------->currFree:31, currThreadCount:32, busy:[1]
sendCondSignal-start.3054648208
onWaitCondSignal.3054648208
sendCondSignal-end.3054648208
>>-------->currFree:31, currThreadCount:32, busy:[1]
sendCondSignal-start.3002198928
onWaitCondSignal.3002198928
sendCondSignal-end.3002198928
>>-------->currFree:31, currThreadCount:32, busy:[1]






但有时候 大概几百次出现一段:
sendCondSignal-start.2886810512
onWaitCondSignal.2886810512
sendCondSignal-end.2886810512
>>-------->currFree:31, currThreadCount:32, busy:[1]
sendCondSignal-start.2750442384
onWaitCondSignal.2750442384
sendCondSignal-end.2750442384
>>-------->currFree:30, currThreadCount:32, busy:[2]
sendCondSignal-start.2865830800
sendCondSignal-end.2865830800
>>-------->currFree:29, currThreadCount:32, busy:[3]
sendCondSignal-start.3086117776
sendCondSignal-end.3086117776
>>-------->currFree:28, currThreadCount:32, busy:[4]
sendCondSignal-start.2960239504
sendCondSignal-end.2960239504
>>-------->currFree:27, currThreadCount:32, busy:[5]
sendCondSignal-start.2897300368
sendCondSignal-end.2897300368
>>-------->currFree:26, currThreadCount:32, busy:[6]
sendCondSignal-start.2813381520
sendCondSignal-end.2813381520
>>-------->currFree:25, currThreadCount:32, busy:[7]
sendCondSignal-start.2802891664
sendCondSignal-end.2802891664
>>-------->currFree:24, currThreadCount:32, busy:[8]
sendCondSignal-start.2855340944
sendCondSignal-end.2855340944
>>-------->currFree:23, currThreadCount:32, busy:[9]
sendCondSignal-start.3033668496
sendCondSignal-end.3033668496
>>-------->currFree:22, currThreadCount:32, busy:[10]
sendCondSignal-start.3065138064
sendCondSignal-end.3065138064
>>-------->currFree:21, currThreadCount:32, busy:[11]
sendCondSignal-start.2991709072
sendCondSignal-end.2991709072
>>-------->currFree:20, currThreadCount:32, busy:[12]
sendCondSignal-start.3054648208
sendCondSignal-end.3054648208
>>-------->currFree:19, currThreadCount:32, busy:[13]
sendCondSignal-start.3002198928
sendCondSignal-end.3002198928
>>-------->currFree:18, currThreadCount:32, busy:[14]
sendCondSignal-start.2792401808
sendCondSignal-end.2792401808
>>-------->currFree:17, currThreadCount:32, busy:[15]
sendCondSignal-start.2771422096
sendCondSignal-end.2771422096
>>-------->currFree:16, currThreadCount:32, busy:[16]
sendCondSignal-start.3023178640
sendCondSignal-end.3023178640
>>-------->currFree:15, currThreadCount:32, busy:[17]
sendCondSignal-start.3044158352
sendCondSignal-end.3044158352
>>-------->currFree:14, currThreadCount:32, busy:[18]
sendCondSignal-start.2949749648
sendCondSignal-end.2949749648
>>-------->currFree:13, currThreadCount:32, busy:[19]
sendCondSignal-start.2781911952
sendCondSignal-end.2781911952
>>-------->currFree:12, currThreadCount:32, busy:[20]
sendCondSignal-start.2844851088
sendCondSignal-end.2844851088
>>-------->currFree:11, currThreadCount:32, busy:[21]
sendCondSignal-start.2760932240
sendCondSignal-end.2760932240
>>-------->currFree:10, currThreadCount:32, busy:[22]
sendCondSignal-start.2981219216
sendCondSignal-end.2981219216
>>-------->currFree:9, currThreadCount:32, busy:[23]
sendCondSignal-start.2834361232
sendCondSignal-end.2834361232
>>-------->currFree:8, currThreadCount:32, busy:[24]
sendCondSignal-start.2928769936
sendCondSignal-end.2928769936
>>-------->currFree:7, currThreadCount:32, busy:[25]
sendCondSignal-start.2823871376
sendCondSignal-end.2823871376
>>-------->currFree:6, currThreadCount:32, busy:[26]
sendCondSignal-start.2876320656
sendCondSignal-end.2876320656
>>-------->currFree:5, currThreadCount:32, busy:[27]
sendCondSignal-start.3012688784
sendCondSignal-end.3012688784
>>-------->currFree:4, currThreadCount:32, busy:[28]
sendCondSignal-start.3075627920
sendCondSignal-end.3075627920
>>-------->currFree:3, currThreadCount:32, busy:[29]
sendCondSignal-start.2970729360
sendCondSignal-end.2970729360
>>-------->currFree:2, currThreadCount:32, busy:[30]
sendCondSignal-start.2939259792
sendCondSignal-end.2939259792
>>-------->currFree:1, currThreadCount:32, busy:[31]
sendCondSignal-start.2886810512
sendCondSignal-end.2886810512
>>-------->currFree:0, currThreadCount:32, busy:[32]
>>save BusyTask to list!
>>save BusyTask to list!
>>save BusyTask to list!
>>save BusyTask to list!
>>save BusyTask to list!
>>save BusyTask to list!
>>save BusyTask to list!
>>save BusyTask to list!
>>save BusyTask to list!
>>save BusyTask to list!
>>save BusyTask to list!
>>save BusyTask to list!
onWaitCondSignal.2865830800
onWaitCondSignal.3086117776
onWaitCondSignal.2960239504
onWaitCondSignal.2897300368
onWaitCondSignal.2813381520
onWaitCondSignal.2802891664
onWaitCondSignal.2855340944
onWaitCondSignal.3033668496
onWaitCondSignal.3065138064
onWaitCondSignal.2991709072
onWaitCondSignal.3054648208
onWaitCondSignal.3002198928
onWaitCondSignal.2792401808
onWaitCondSignal.2771422096
onWaitCondSignal.3023178640
onWaitCondSignal.3044158352
onWaitCondSignal.2949749648
onWaitCondSignal.2781911952
onWaitCondSignal.2844851088
onWaitCondSignal.2760932240
onWaitCondSignal.2981219216
onWaitCondSignal.2834361232
onWaitCondSignal.2928769936
onWaitCondSignal.2823871376
onWaitCondSignal.2876320656
onWaitCondSignal.3012688784
onWaitCondSignal.3075627920
onWaitCondSignal.2970729360
onWaitCondSignal.2939259792
onWaitCondSignal.2886810512



发送信号那里像阻塞了一样 之后一起爆发...

class TPThread
{
protected:
pthread_cond_t cond; // 线程信号量
pthread_mutex_t mutex; // 线程互诉体

static thread_function()...

virtual void initCond( void )
{
pthread_cond_init( &cond, NULL );
}



...全文
3542 58 打赏 收藏 转发到动态 举报
写回复
用AI写文章
58 条回复
切换为时间正序
请发表友善的回复…
发表回复
flyword123 2012-08-04
  • 打赏
  • 举报
回复
我也遇到了类似的问题,同求指导
旭子 2011-09-16
  • 打赏
  • 举报
回复
频繁的话就用自旋锁
wzb56 2011-09-01
  • 打赏
  • 举报
回复
关注!
mozei 2011-07-18
  • 打赏
  • 举报
回复
mark
dos5gw 2011-07-18
  • 打赏
  • 举报
回复
while(queue != NULL)
pthread_cond_wait()

我一般这样写
xf_21 2011-06-28
  • 打赏
  • 举报
回复
你下面这个函数根本没有写完整,应该还有关键的语句

static thread_function(arg): 线程函数大概这样
TPThread* tptd = arg;
while(1)
{
pthread_cond_wait( &tptd->cond, &tptd->mutex );
printf( "onWaitCondSignal.%u\n", pthread_self() );

处理任务....
}

不妨贴出来。
xf_21 2011-06-28
  • 打赏
  • 举报
回复
对于这种问题,最好把代码全贴出来。不要怕泄露源码什么的,现在源码不是90年代那么珍稀了。

一般而言,出问题都是自己代码的问题,或者是对某个函数或者变量的工作方式不太了解,或者是逻辑方面有错误,好好检查吧。

如果实在不行,就想个容错的办法处理之。
amloy520 2011-05-02
  • 打赏
  • 举报
回复
我有一个线程池, 通过信号来唤醒指定的线程开始工作, 但我发现经常有频率的pthread_cond_signal( &cond );会不能及时的唤醒一个线程, 而导致闲置线程进入繁忙状态后却没有醒过来工作, 导致了大量的繁忙线程增加, 直接导致线程池效率降低。

任务进入繁忙状态,没有退出 ,说明你的任务没有完成,既然你的任务什么也没干,说明你有一个地方导致你一但进入任务就无法退出,这些都是很明显的,最好是把代码贴下,你的线程池代码也不是密码代码,写个为逻辑也可以。
我不用epoll, 我用的是这个模型, http://unsoundboy.iteye.com/blog/713265,但我觉得跟epoll 的关系不大,没有理由去怀疑一个lib库的有问题,就像你去怀疑fstream是不是线程安全一样。
ketao_78 2011-02-14
  • 打赏
  • 举报
回复
[Quote=引用 13 楼 guosha 的回复:]

肯定不会是虚拟机的问题啦!可能是你哪里出现了死锁吧。你最好把你出问题的最简代码全帖出来。
[/Quote]

agree
海枫 2010-12-01
  • 打赏
  • 举报
回复
那是因为你的singnal和wait使用不当而造成的,#46楼有解释。
海枫 2010-11-03
  • 打赏
  • 举报
回复
有race condition。

pthread_cond_signal和pthread_cond_wait是异步通知和等待,如果signal发生在wait前面,那么wait会等待下一个signal,这与linux下的signal在概念是一致(我们抛开它的实现)。

因它使用pthread 的这些API,开发人员必须保持这些异步情况得到控制,这样,你的程序才能证明是否是线程安全的。

比如在mutex的region里面才使用pthread_cond_signal和pthread_cond_wait

void *send_thread(void *)
{
while(1)
{
lock(mutex);
// calculate something
// put the stubff to share buffer
signal(cond);
unlock(mutex);
}
}

void *recv_thread(void *)
{
lock(&mutex)
while(1)
{
wait(cond, mutex);
if(condition are not true)
continue;

// fetch stuff from buffer
// deal with it.
}
}
zhuxueling 2009-11-25
  • 打赏
  • 举报
回复
我好像看过epoll_wait的代码,不过也没看出什么东西来。
就是设置一个唤醒条件,之后让出CPU执行权,把调用线程投入睡眠。

我没看出什么东西,也就不多说了。。。
至少在看到代码之前

为什么好多人都喜欢你以那种方式实现线程池呢? 我就很不喜欢那种方式,
我喜欢用一个线程安全的任务队列。
无知者无谓 2009-10-23
  • 打赏
  • 举报
回复
线程调用问题?
看看发生这种情况CPU的状况吧
kuangrenlan 2009-09-03
  • 打赏
  • 举报
回复
把完整的代码再贴一遍吧
LiquidX 2009-03-26
  • 打赏
  • 举报
回复
哎, 晕, 我来问问提, 既然要我指点, 我还是自己去看epoll源代码吧。
gxj760998 2009-03-26
  • 打赏
  • 举报
回复
不要叫我大牛, 我是来问问题的

LZ兄弟,对不起,我还真不是问你。
我也写过几年代码,多少还是看得出来点端倪。

我其实只想弄明白一件事情,你这样的问题到底是如何产生的,而我看得不够清晰,所以希望高手指点下,解释下。
aflyinghorse 2009-03-26
  • 打赏
  • 举报
回复
help ding
hujun_zero 2009-03-26
  • 打赏
  • 举报
回复
顶!学习
LiquidX 2009-03-25
  • 打赏
  • 举报
回复
[Quote=引用 32 楼 gxj760998 的回复:]
epoll_wait( kdpfd, events, curfds, -1 );
LZ回去补充下多线程的同步中关于EVENT方式再来提问吧。
你的程应该是等待资源的多,释放资源的少。
[/Quote]

每个线程有自己独立的 pthread_cond ,pthread_mutex_t
等待也是等待自己的, 不存在任何问题,没有 epoll_wait的话, 线程用while(1)的速度去执行都用的很happy,


static void *epoll_thread( void*arg)
{
while(1)
{
epoll_wait( kdpfd, events, curfds, -1 );
for( int n=0; n<100; n++ )
ThreadPool::addTask( TaskNULL() );
}
}

TaskNULL本身不做任何事情. 这里也只是象征性的调用epoll_wait处理事件而已.
sendCondSignal-start.2855340944 出现这个调试信息 是调用了addTask导致的
去掉epoll_wait就正常, 不知道你能否解释和同步有什么关系?



我已经换了方式 多线程epoll, 现在一切都很happy。
gxj760998 2009-03-25
  • 打赏
  • 举报
回复
epoll_wait( kdpfd, events, curfds, -1 );
LZ回去补充下多线程的同步中关于EVENT方式再来提问吧。
你的程应该是等待资源的多,释放资源的少。
加载更多回复(36)

23,120

社区成员

发帖
与我相关
我的任务
社区描述
Linux/Unix社区 应用程序开发区
社区管理员
  • 应用程序开发区社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧