简易线程池实现

来源:互联网 发布:marjakurki知乎 编辑:程序博客网 时间:2024/04/26 06:23

是其实也就是任务分发器,池子里预先跑着N个线程,可以往池子里提交任务。相对线程不断创建和销毁,特别对于大量的短时任务,线程池显然是很节省资源的。直接上代码:

#include <stdio.h>#include <errno.h>#include <stdlib.h>#include <pthread.h>#include <unistd.h>#include <string.h>typedef void* (*job)(void*);#define THREAD_PROC(i) (thread##i)struct pthread_pool_t {pthread_mutex_t lock;pthread_rwlock_t flag_lock;pthread_t id;job working_job;int flag;void* job_args;struct pthread_pool_t* next;};void init_pool(struct pthread_pool_t* pool){pool->id = 0;pool->working_job = 0;pool->flag = 0;pool->next = NULL;pool->job_args = 0;pthread_mutex_init(&pool->lock,NULL);pthread_rwlock_init(&pool->flag_lock,NULL);}void print_pool(struct pthread_pool_t* pool){#if 0printf("pool->lock = 0x%x\n",pool->lock);printf("pool->id = 0x%x\n",pool->id);printf("pool->working_job = 0x%x\n",pool->working_job);printf("pool->flag = 0x%x\n",pool->flag);printf("pool->args = 0x%x\n",pool->job_args);printf("pool->next = 0x%x\n",pool->next);#endif}void* thread1(void* p){struct pthread_pool_t* ptr = (struct pthread_pool_t*)(p);while(1){//set a rwlock  write-mode here ,  post_job will block there,//only when ptr->flag is changedpthread_rwlock_wrlock(&ptr->flag_lock);/*printf("thread1 ... lock here\n");*/pthread_mutex_lock(&(ptr->lock));printf("thread1 got job = 0x%x\n",(unsigned int)ptr->working_job);if(ptr->flag == 1){ptr->flag = 0;pthread_rwlock_unlock(&ptr->flag_lock);(*ptr->working_job)(ptr->job_args);}//ptr->flag = 0;//printf("thread1 done\n");ptr->flag = 1;//pthread_mutex_lock(&(ptr->lock));}return (void*)0;}void* thread2(void* p){struct pthread_pool_t* ptr = (struct pthread_pool_t*)(p);while(1) {pthread_rwlock_wrlock(&ptr->flag_lock);/*printf("thread2 ... lock here\n");*/pthread_mutex_lock(&(ptr->lock));printf("thread2 got job = 0x%x\n",(unsigned int)ptr->working_job);if(ptr->flag == 1){ptr->flag = 0;pthread_rwlock_unlock(&ptr->flag_lock);(*ptr->working_job)(ptr->job_args);}//ptr->flag = 0;//printf("thread2 done\n");ptr->flag = 1;//pthread_mutex_lock(&(ptr->lock));}return (void*)0;}void* thread3(void* p){struct pthread_pool_t* ptr = (struct pthread_pool_t*)(p);while(1) {pthread_rwlock_wrlock(&ptr->flag_lock);/*printf("thread3 ... lock here\n");*/pthread_mutex_lock(&(ptr->lock));printf("thread3 got job = 0x%x\n",(unsigned int)ptr->working_job);if(ptr->flag == 1){ptr->flag = 0;pthread_rwlock_unlock(&ptr->flag_lock);(*ptr->working_job)(ptr->job_args);}//printf("thread3 done\n");ptr->flag = 1;//pthread_mutex_lock(&(ptr->lock));}return (void*)0;}int init_pthread_pool(struct pthread_pool_t** pool){int i = 0;job prepared_job[3] = {0};struct pthread_pool_t* ptr = NULL;struct pthread_pool_t* old = NULL;prepared_job[0] = thread1;prepared_job[1] = thread2;prepared_job[2] = thread3;for(;i < 3 ; i++) {//printf("malloc\n");ptr = (struct pthread_pool_t* )malloc(sizeof(struct pthread_pool_t));init_pool(ptr);/*//print_pool(ptr);*/if(old != NULL) {old->next = ptr;//printf("old->next = ptr\n");}if(ptr == NULL) {printf("init_pthread_pool malloc error\n");return -1;}//Header fixedif(*pool == NULL) {//printf("*pool\n");*pool = ptr;}//Init flagptr->flag = 1;//ptr->lock = PTHREAD_MUTEX_INITIALIZER;//Lock firstpthread_mutex_lock(&(ptr->lock));pthread_create(&(ptr->id),NULL,prepared_job[i],ptr);//Nextold = ptr;//printf("old = ptr\n");}/*printf("pool = 0x%x\n",(int)pool);*///printf("In init\n");////print_pool(*pool);//Wait all thread readysleep(1);return 0;}void release_pthread_pool(struct pthread_pool_t* header){if(header == NULL)return;struct pthread_pool_t* ptr_pool = header;struct pthread_pool_t* ptr_free = ptr_pool;while(ptr_pool->next != NULL){ptr_pool = ptr_pool->next;pthread_mutex_destroy(&(ptr_free->lock));pthread_rwlock_destroy(&(ptr_free->flag_lock));pthread_cancel(ptr_pool->id);free(ptr_free);ptr_free = ptr_pool;}free(ptr_pool);}/** * @brief post_job  * @param job * @param args * @param pool * @return   */int post_job(job job,void* args, struct pthread_pool_t* pool){int ret;struct pthread_pool_t* ptr = pool;//printf("head = 0x%x\n",(int)ptr);//get non-busy thread idwhile(ptr != NULL) {//printf("post_job Start flag = %d\n",ptr->flag);//Avoid dead lockret = pthread_rwlock_tryrdlock(&ptr->flag_lock);if(ret != 0) {//printf("Sleep for a while\n");//usleep(10000);} else {printf("Should not lock\n");pthread_rwlock_unlock(&(ptr->flag_lock));}//print_pool(ptr);//try to get flag lock here if not blockif(ptr->flag == 1) {//printf("post_job Register job=0x%x\n",job);ptr->working_job = job;ptr->job_args = args;//deliver job to thread`pthread_mutex_unlock(&(ptr->lock));//ptr->flag = 0;return 0;} else {//printf("post_job Next\n");ptr = ptr->next;}}printf("Ptr == NULL\n");//Ptr == NULL  or pool busy , still not find a working_job.return -1;}int remove_job(job job,struct pthread_pool_t* pool) {return 0;}void* a_job(void* args){printf("Job a running\n");sleep(1);printf("Job a done\n");return (void*)0;}void* b_job(void* args){printf("Job b running\n");sleep(1);printf("Job b done\n");return (void*)0;}void* c_job(void* args){printf("Job c running\n");printf("Job c done\n");return (void*)0;}int main(int argc, char* argv[]){printf("Go\n");int ret;struct pthread_pool_t* ThreadPool = NULL;init_pthread_pool(&ThreadPool);#if 1//printf("ThreadPool\n");//print_pool(ThreadPool);#endif/*printf("ThreadPool = 0x%x\n",(struct pthread_pool_t*)(&ThreadPool));*/#if 0ret = post_job(a_job,NULL, ThreadPool);if(ret)printf("post_job 1 failed\n");ret = post_job(b_job,NULL, ThreadPool);if(ret)printf("post_job 2 failed\n");ret =post_job(c_job,NULL, ThreadPool);if(ret)printf("post_job 3 failed\n");#endifint count = 0;do{if(count % 2)ret =post_job(c_job,NULL, ThreadPool);else ret =post_job(a_job,NULL, ThreadPool);if(ret)printf("post_job may failed\n");printf("Count = %d\n",count);usleep(200000);}while(count++ < 100);release_pthread_pool(ThreadPool);getchar();return 0;}

运行结果

取count=5

Go
Count = 0
thread1 got job = 0x40101f
Job a running
Should not lock
Count = 1
thread2 got job = 0x401081
Job c running
Job c done
Should not lock
Count = 2
thread2 got job = 0x40101f
Job a running
Should not lock
Should not lock
Count = 3
thread3 got job = 0x401081
Job c running
Job c done
Should not lock
Should not lock
Count = 4
thread3 got job = 0x40101f
Job a running
Job a done
Count = 5
thread1 got job = 0x401081
Job c running
Job c done

说明

post_job是异步的。在资源不足时,提交会失败。
提交的任务越密集,池子初始化的线程越少,提交越容易失败。
实现的关键也是post_job.使用了两把锁:
一把锁是post_job唤醒thread,之后调用job的cb;
另一把锁,用来同步flag。使用trylock防止第1死锁。

0 0
原创粉丝点击