POSIX标准下的线程池的简单实现
一 条件变量操作
函数名 | 功能 | 函数原型 |
---|---|---|
pthread_cond_init | 条件变量的初始化 | int pthread_cond_init(pthread_cond_t*cv,const pthread_condattr_t *cattr); |
pthread_cond_wait | 等待(阻塞)在条件变量上 | int pthread_cond_wait(pthread_cond_t *cv,pthread_mutex_t *mutex); |
pthread_cond_timedwait | 阻塞直到指定时间 | int pthread_cond_timedwait(pthread_cond_t cv,pthread_mutex_t *mp, const structtimespec abstime); |
pthread_cond_signal | 解除在条件变量上的阻塞 | int pthread_cond_signal(pthread_cond_t *cv); |
pthread_cond_broadcast | 释放阻塞的所有线程 | int pthread_cond_broadcast(pthread_cond_t *cv); |
pthread_cond_destroy | 释放条件变量 | int pthread_cond_destroy(pthread_cond_t *cv); |
函数详细解析请参考http://blog.csdn.net/ffilman/article/details/4871920
注:pthread_cond_broadcast 只会对当前所有阻塞的条件变量进行广播。而为未阻塞的条件变量不会受任何影响。
二 互斥锁的操作
函数名 | 功能 | 函数原型 |
---|---|---|
pthread_mutex_init | 初始化互斥锁 | int pthread_mutex_init(pthread_mutex_t *restrict mutex,const pthread_mutexattr_t *restrict attr); |
pthread_mutex_lock() | 加锁,如果尝试锁定已经被上锁的互斥锁则阻塞至可用为止 | int pthread_mutex_lock(pthread_mutex_t *mutex); |
pthread_mutex_trylock() | 加锁,非阻塞版的pthread_mutex_lock | int pthread_mutex_trylock( pthread_mutex_t *mutex ); |
pthread_mutex_unlock() | 解锁 | int pthread_mutex_unlock(pthread_mutex_t *mutex); |
pthread_mutex_destroy() | 销毁互斥锁 | int pthread_mutex_destroy(pthread_mutex_t *mutex); |
三 线程函数的操作
函数名 | 功能 | 函数原型 |
---|---|---|
pthread_create() | 线程创建函数 | int pthread_create(pthread_t restrict tid,const pthread_attr_t *restrict attr,void (start_rtn)(void ),void *restrict arg); |
pthread_self() | 获取线程自身id | pthread_t pthread_self(void); |
pthread_join() | 等待一个线程结束 | int pthread_join(pthread_t thread, void **retval); |
pthread_kill() | 给一个线程发送信号 | int pthread_kill(pthread_t thread, int sig); |
pthread_exit() | 线程退出函数 | void pthread_exit(void* retval); |
四 线程池的实现
线程池的适用范围:适用于多CPU大量任务简单执行时间段的情况
本线程池通过互斥量和条件变量的组合使用来对生产者消费者
模型进行控制,通过链表实现任务队列功能,满足任务的顺序执行。线程
执行任务的函数为测试代码main.c中的void *mytask(void *arg){};需要执行其他任务时,可以重写该函数。
以下是其的简单实现:
condition.h
#ifndef __CONDITION_H_
#define __CONDITION_H_
#include <pthread.h>
#include <time.h>
typedef struct condition
{
pthread_mutex_t pmutex;
pthread_cond_t pcond;
} condition_t;
int condition_init(condition_t *cond);
int condition_lock(condition_t *cond);
int condition_unlock(condition_t *cond);
int condition_wait(condition_t *cond);
int condition_timedwait(condition_t *cond,const struct timespec *abstime);
int condition_signal(condition_t *cond);
int condition_broadcast(condition_t *cond);
int condition_destroy(condition_t *cond);
#endif
condition.c
#include "condition.h"
int condition_init(condition_t *cond)
{
int status;
if(status = pthread_mutex_init(&cond->pmutex,NULL))
{
return status;
}
if(status = pthread_cond_init(&cond->pcond,NULL))
{
return status;
}
return 0;
}
int condition_lock(condition_t *cond)
{
return pthread_mutex_lock(&cond->pmutex);
}
int condition_unlock(condition_t *cond)
{
return pthread_mutex_unlock(&cond->pmutex);
}
int condition_wait(condition_t *cond)
{
return pthread_cond_wait(&cond->pcond,&cond->pmutex);
}
int condition_timedwait(condition_t *cond,const struct timespec *abstime)
{
return pthread_cond_timedwait(&cond->pcond,&cond->pmutex,abstime);
}
int condition_signal(condition_t *cond)
{
return pthread_cond_signal(&cond->pcond);
}
int condition_broadcast(condition_t *cond)
{
return pthread_cond_broadcast(&cond->pcond);
}
int condition_destroy(condition_t *cond)
{
int status;
if(status = pthread_mutex_destroy(&cond->pmutex));
{
return status;
}
if(status = pthread_cond_destroy(&cond->pcond));
{
return status;
}
return 0;
}
pthread.h
# ifndef __PTHREAD_H
# define __PTHREAD_H
#include "condition.h"
//任务结构体,将任务放入队列由线程池中的线程来执行
typedef struct task
{
void *(*run)(void *arg); //任务回调函数
void *arg; //回调函数参数
struct task *next;
} task_t;
//线程池结构体
typedef struct threadpool
{
condition_t ready; //任务准备就绪或者线程池销毁通知
task_t *first; //任务队列头指针
task_t *last; //任务队列尾指针
int counter; //线程池中当前线程数
int idle; //线程池中当前正在等待任务(空闲)的线程数
int max_threads; //线程池中最大允许的线程数
int quit; //销毁线程池的时候置1
} threadpool_t;
//初始化线程池
void threadpool_init(threadpool_t *pool,int threads);
//往线程池中添加任务
void threadpool_add_task(threadpool_t *pool,void *(*run)(void *arg),void *arg);
//销毁线程池
void threadpool_destroy(threadpool_t *pool);
#endif
pthread.c
# include <string.h>
# include <errno.h>
# include <time.h>
# include <stdio.h>
# include <stdlib.h>
# include <time.h>
# include "pthread.h"
//创建线程给的函数,线程处理函数
void *thread_routine(void *arg)
{
struct timespec abstime;
int timeout=0;
printf("thread 0x%0x is starting.\n",(int)pthread_self());
threadpool_t *pool=(threadpool_t *) arg;
while(1)
{
timeout = 0;
condition_lock(&pool->ready);
pool->idle++;
//等待对列有任务到来或者线程销毁通知
while(pool->first == NULL && !pool->quit)
{
printf("thread 0x%0x is waiting.\n",(int)pthread_self());
/*等待超时,任务队列没有任务*/
//condition_wait(&pool->ready);
clock_gettime(CLOCK_REALTIME,&abstime);
abstime.tv_sec += 2;
int status = condition_timedwait(&pool->ready,&abstime);
if (status == ETIMEDOUT)
{
printf("thread 0x%0x is wait time out.\n",(int)pthread_self());
timeout=1;
break;
}
}
//等待到条件,处于工作状态
pool->idle--;
if(pool->first !=NULL)
{
//从头取出任务
task_t *t=pool->first;
pool->first=t->next;
//执行任务需要一定的时间,所以要解锁,以便生产者进程能够往队列中
//添加任务,其他消费者线程能够进入等待任务
condition_unlock(&pool->ready);
t->run(t->arg);
free(t);
condition_lock(&pool->ready);
}
//如果等待到线程池销毁通知,并且任务队列为空
if(pool->quit && pool->first == NULL)
{
pool->counter--;
/*如果当前线程为0*/
if(pool->counter == 0)
{
condition_signal(&pool->ready);
}
condition_unlock(&pool->ready);
break;
}
//超时
if(timeout && pool->first == NULL)
{
pool->counter--;
condition_unlock(&pool->ready);
break;
}
condition_unlock(&pool->ready);
}
printf("thread 0x%0x is exiting.\n",(int)pthread_self());
return NULL;
}
//初始化线程池
void threadpool_init(threadpool_t *pool,int threads)
{
condition_init(&pool->ready);
pool->first=NULL;
pool->last=NULL;
pool->counter=0;
pool->idle=0;
pool->max_threads=threads;
pool->quit=0;
}
//往线程池中添加任务
void threadpool_add_task(threadpool_t *pool,void *(*run)(void *arg),void *arg)
{
/*生成一个新任务*/
task_t *newtask = (task_t*)malloc(sizeof(task_t));
newtask->run=run;
newtask->arg=arg;
newtask->next=NULL;
condition_lock(&pool->ready);
/*将任务添加到任务队列*/
if(pool->first == NULL)
{
pool->first=newtask;
} else{
pool->last->next=newtask;
}
pool->last=newtask;
/*,如果有空闲线程,唤醒线程*/
if(pool->idle>0)
{
condition_signal(&pool->ready);
}else if(pool->counter < pool->max_threads)
{
//没有等待线程,并且当前线程数不超过最大线程数,则创建一个新线程
pthread_t tid;
pthread_create(&tid,NULL,thread_routine,pool);
pool->counter++;
}
condition_unlock(&pool->ready);
}
//销毁线程池
void threadpool_destroy(threadpool_t *pool)
{
if(pool->quit)
{
return;
}
condition_lock(&pool->ready);
pool->quit = 1;
if(pool->counter > 0)
{
if(pool->idle > 0)
{
//广播
condition_broadcast(&pool->ready);
}
//处于执行任务状态的线程不会收到广播,线程池需要等待执行
//任务状态的线程全部退出
while(pool->counter > 0)
{
condition_wait(&pool->ready);
}
}
condition_unlock(&pool->ready);
condition_destroy(&pool->ready);
}
main.c
#include <stdio.h>
#include <stdlib.h>
#include <stdlib.h>
#include <unistd.h>
#include "pthread.h"
void *mytask(void *arg)
{
printf("thread 0x%0x is working on task %d.\n",(int)pthread_self(),*(int*)arg);
sleep(1);
free(arg);
return NULL;
}
int main()
{
threadpool_t pool;
threadpool_init(&pool,3);
int i;
for(i=0;i<10;i++)
{
int *arg = (int*)malloc(sizeof(int));
*arg = i;
threadpool_add_task(&pool,mytask,arg);
}
threadpool_destroy(&pool);
return 0;
}
Makefile
pool:main.o pthread.o condition.o
gcc -Wall -g condition.o pthread.o main.o -o pool -lpthread -lrt
main.o:main.c
gcc -Wall -g -c main.c
pthread.o:pthread.c
gcc -Wall -g -c pthread.c
condition.o:condition.c
gcc -Wall -g -c condition.c
clean :
rm condition.o pthread.o main.o