为什么我线程池5个线程,打印ready ,weakup总有时候只有3,4次,然而执行print任务函数却5个线程都执行???

adlatereturn 2020-04-20 02:38:38
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include<sys/mman.h>
#include<pthread.h>
#include<semaphore.h>
#include <netinet/in.h>
#include<sys/socket.h>
#include<arpa/inet.h>
#include<sys/select.h>
#include<sys/epoll.h>
#include<unistd.h>
#include<dirent.h>
#include<pwd.h>
#include<grp.h>
#include<time.h>
#include<errno.h>
#include<signal.h>
#include<fcntl.h>
#include<sys/wait.h>
#include<stdbool.h>
typedef void Fun(void*);

typedef struct work_t{
Fun* fun;
void*arg;
struct work_t*next;
}work_t;

typedef struct trdpool_t{
pthread_t *phead;
work_t *whead;
pthread_cond_t cond;
pthread_mutex_t mutex;
bool status; //0 线程池不销毁 1 销毁
int num;
}trdpool_t;

trdpool_t *trdpool=NULL;

void print_pthread_self(void*arg)
{
//sleep(3);
printf("pthread id = %ld\n",pthread_self());
//sleep(2);
return ;
}
void*start_routine(void*arg)
{
// puts("!");
work_t*work;
while(1){
pthread_mutex_lock(&trdpool->mutex);
// puts("?");
while( trdpool->whead==NULL&& trdpool->status==0){ //一个小朋友把蛋糕抢走了,那么其他小朋友醒来再继续睡。
fprintf(stdout,"thread %ld is ready \n",pthread_self());

pthread_cond_wait(& trdpool->cond,& trdpool->mutex);
sleep(1);
fprintf(stdout,"thread %ld is weak up \n",pthread_self());

}
if( trdpool->status==0){
work= trdpool->whead;
trdpool->whead= trdpool->whead->next;
pthread_mutex_unlock(& trdpool->mutex);
(work->fun)(work->arg);
free(work);
}else{
pthread_mutex_unlock(& trdpool->mutex);
pthread_exit(NULL);
}
}
}


void add_work()
{
work_t* new_work=malloc(sizeof(work_t));
work_t* old_work;
new_work->arg=NULL;
new_work->fun=print_pthread_self;
new_work->next=NULL;
pthread_mutex_lock(& trdpool->mutex);
if( trdpool->whead!=NULL){
old_work= trdpool->whead;
trdpool->whead=new_work;
new_work->next=old_work;
}else{
trdpool->whead=new_work;
}
pthread_cond_signal(& trdpool->cond);
pthread_mutex_unlock(& trdpool->mutex);
}


void prdpool_init(int num)
{
trdpool=malloc(sizeof(trdpool_t));
pthread_mutex_init(& trdpool->mutex,NULL);
pthread_cond_init(& trdpool->cond,NULL);

trdpool->status=0;
trdpool->phead=malloc(sizeof(pthread_t)*num);
trdpool->num=num;
for(int i=0;i<num;i++)
pthread_create( trdpool->phead+i,NULL,start_routine,NULL);
}
void prdpool_destory()
{
puts("the trdpool begin to destory !");

work_t *work;
trdpool->status=1;

int ret=pthread_mutex_lock(& trdpool->mutex);
pthread_cond_broadcast(& trdpool->cond);
pthread_mutex_unlock(& trdpool->mutex);
for(int i=0;i< trdpool->num;i++){
pthread_join( trdpool->phead[i],NULL);
}
free( trdpool->phead);
work=trdpool->whead;
while(trdpool->whead){
// puts("!");
trdpool->whead=trdpool->whead->next;
free(work);
work=trdpool->whead;
}
pthread_cond_destroy(& trdpool->cond);
pthread_mutex_destroy(& trdpool->mutex);
free(trdpool);
puts("the trdpool destory !");
}


int main(int argc,char**argv)
{
prdpool_init(5);

for(int i=0;i<200;i++)
add_work();
sleep(5);
// while(1);
prdpool_destory();
return 0;
}



为什么我线程池5个线程打印ready ,weakup总有时候只有3,4次,然而执行print任务函数却5个线程都执行???
是哪里有缓冲的的问题吗???
...全文
170 6 打赏 收藏 转发到动态 举报
写回复
用AI写文章
6 条回复
切换为时间正序
请发表友善的回复…
发表回复
adlatereturn 2020-04-20
  • 打赏
  • 举报
回复
引用 5 楼 bo_self_effacing 的回复:
[quote=引用 4 楼 adlatereturn 的回复:] [quote=引用 3 楼 bo_self_effacing 的回复:] while( trdpool->whead==NULL&& trdpool->status==0) 要是addwork先拿到锁 把状态改了 你这里不就进不去了吗 怎么打印
你说的对,线程还没进来。那还有别的好的处理方式吗???[/quote] 阻塞肯定得阻塞的, 就算你用锁也是阻塞的,我的话可能会在 init 后面加: void prdpool_init(int num) { trdpool=malloc(sizeof(trdpool_t)); pthread_mutex_init(& trdpool->mutex,NULL); pthread_cond_init(& trdpool->cond,NULL); trdpool->status=0; trdpool->phead=malloc(sizeof(pthread_t)*num); trdpool->num=num; for(int i=0;i<num;i++) pthread_create( trdpool->phead+i,NULL,start_routine,NULL); lblready: 遍历检查封装的 线程结构 { pthread_t a, char state } 就不只是你现在的 pthread_t *phead 在线程拿到锁后就可以state = 1 表示准备好了 { if(state == 0) //usleep(...) 要不要sleep看你 goto lblready; } }[/quote]懂了谢谢!
tobybo 2020-04-20
  • 打赏
  • 举报
回复
引用 4 楼 adlatereturn 的回复:
[quote=引用 3 楼 bo_self_effacing 的回复:] while( trdpool->whead==NULL&& trdpool->status==0) 要是addwork先拿到锁 把状态改了 你这里不就进不去了吗 怎么打印
你说的对,线程还没进来。那还有别的好的处理方式吗???[/quote] 阻塞肯定得阻塞的, 就算你用锁也是阻塞的,我的话可能会在 init 后面加: void prdpool_init(int num) { trdpool=malloc(sizeof(trdpool_t)); pthread_mutex_init(& trdpool->mutex,NULL); pthread_cond_init(& trdpool->cond,NULL); trdpool->status=0; trdpool->phead=malloc(sizeof(pthread_t)*num); trdpool->num=num; for(int i=0;i<num;i++) pthread_create( trdpool->phead+i,NULL,start_routine,NULL); lblready: 遍历检查封装的 线程结构 { pthread_t a, char state } 就不只是你现在的 pthread_t *phead 在线程拿到锁后就可以state = 1 表示准备好了 { if(state == 0) //usleep(...) 要不要sleep看你 goto lblready; } }
adlatereturn 2020-04-20
  • 打赏
  • 举报
回复
引用 3 楼 bo_self_effacing 的回复:
while( trdpool->whead==NULL&& trdpool->status==0) 要是addwork先拿到锁 把状态改了 你这里不就进不去了吗 怎么打印
你说的对,线程还没进来。那还有别的好的处理方式吗???
tobybo 2020-04-20
  • 打赏
  • 举报
回复
while( trdpool->whead==NULL&& trdpool->status==0) 要是addwork先拿到锁 把状态改了 你这里不就进不去了吗 怎么打印
adlatereturn 2020-04-20
  • 打赏
  • 举报
回复
引用 1 楼 bo_self_effacing 的回复:
prdpool_init(5); //这里sleep(1) 暂停一下 等 线程全部趴在cond_wait那里了 再执行下面的 addwork也会和他们抢锁 for(int i=0;i<200;i++) add_work();
争锁是一回事 打印是另一回事,那个sleep(1)的确可以打印出5条,但是没有sleep的情况下这些线程也是去执行了work却没有打印ready和weakup!!!岂不怪哉!!!
tobybo 2020-04-20
  • 打赏
  • 举报
回复
prdpool_init(5); //这里sleep(1) 暂停一下 等 线程全部趴在cond_wait那里了 再执行下面的 addwork也会和他们抢锁 for(int i=0;i<200;i++) add_work();

69,394

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

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