/********************************************************************************
//作者:Honglizheng 原帖地址 http://www.cnblogs.com/newth/archive/2012/05/09/2492459.html
//
//线程池技术:1.创建2个结构体,一个为链表,另外
//一个为线程池基本信息的结构体。
//主要使用的技术难点为:
//1.添加函数指针到一个链表中,这个链表就存储这个函数的指针和参数;
//2.循环一次性为一个函数中创建最大的线程,
//3.然后每个线程就查看链表是否还有任务没有被处理,有没处理的就及时处理,然后释放内存
***********************************************************************************/
/********************************************************************************
//大神的解释:
//你的这个work是局部变量,既不是static,也不是const,外面怎么能看见呢,然后你这样
//是想试用队列模型一边插入一边读取,这样有个坏处,对于锁的争用是很明显的,并发是上不去的
//,你可以试用多队列模型,或者是双缓冲多队列模型,将两个锁分开,只能帮到你这里了
**********************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <pthread.h>
#include <assert.h>
typedef struct thread{
void *(*process)(void *arg);
void *arg;
struct thread *next;
}thread_worker;
typedef struct poll{
//线程锁 条件变量
pthread_mutex_t queue_lock;
pthread_cond_t queue_ready;
//链表,线程池所有任务
thread_worker *queue_head;
//是否销毁线程池
int shutdown;
pthread_t *threadid;
//允许活动的线程数目
int max_thread_num;
//当前等待任务数
int cur_queue_size;
}thread_poll;
static thread_poll *my_pool=NULL;
static void *thread_process(void *arg)
{
thread_worker *thread_node = NULL;
for(;;)
{
//循环处理链表里面包含的任务;
pthread_mutex_lock(&my_pool->queue_lock);
while((my_pool->queue_head&&my_pool->shutdown) == NULL)
{
//pthread_cond_wait会先将 mutex unlock,等到wait返回时,再把 mutex 重新 lock 住。
//当临界资源改变后这个函数的阻塞解除
pthread_cond_wait(&my_pool->queue_ready,&my_pool->queue_lock);
}
//线程池关闭,退出线程
if(my_pool->shutdown){
pthread_mutex_unlock(&my_pool->queue_lock);
pthread_exit(NULL);
}
thread_worker *thread_node = my_pool->queue_head;
my_pool->queue_head = my_pool->queue_head->next;
pthread_mutex_unlock(&my_pool->queue_lock);
thread_node->process(thread_node->arg);
//thread_node为局部变量,所以不用考虑其他函数会修改它
//因为每个线程有各自的线程栈,维护所有函数参数以及局部变量
free(thread_node);
}
}
void *pool_init(int max_thread_num)
{
my_pool=(thread_poll *)malloc(sizeof(thread_poll));
//初始化锁
pthread_mutex_init(&(my_pool->queue_lock),NULL);
//初始化条件变量
pthread_cond_init(&(my_pool->queue_ready),NULL);
my_pool->queue_head = NULL;
my_pool->shutdown = 0;
//申请足够大的空间来保存线程句柄
my_pool->threadid = (pthread_t*)malloc(max_thread_num*sizeof(pthread_t));
my_pool->max_thread_num = max_thread_num;
int i;
for(i=0;i<max_thread_num;i++)
{
pthread_create(&(my_pool->threadid[i]) ,NULL ,thread_process ,NULL);
}
return my_pool;
}
/* 销毁线程池 */
void pool_destroy()
{
int i;
thread_worker *member;
if (my_pool->shutdown) {
return;
}
my_pool->shutdown = 1;
/* 通知所有正在等待的线程 */
pthread_mutex_lock(&my_pool->queue_lock);
pthread_cond_broadcast(&my_pool->queue_ready);
pthread_mutex_unlock(&my_pool->queue_lock);
for (i = 0; i < my_pool->max_thread_num; ++i) {
pthread_join(my_pool->threadid[i], NULL);
}
free(my_pool->threadid);
while(my_pool->queue_head) {
member = my_pool->queue_head;
my_pool->queue_head = my_pool->queue_head->next;
free(member);
}
pthread_mutex_destroy(&my_pool->queue_lock);
pthread_cond_destroy(&my_pool->queue_ready);
free(my_pool);
}
/* 向线程池添加任务 */
int pool_add_work(void*(*process)(void*), void *arg)
{
thread_worker *work, *member;
if (!process){
printf("%s:Invalid argument\n", __FUNCTION__);
return -1;
}
work = malloc(sizeof(thread_worker));
if (!work) {
printf("%s:malloc failed\n", __FUNCTION__);
return -1;
}
work->process = process;
work->arg = arg;
work->next = NULL;
pthread_mutex_lock(&my_pool->queue_lock);
member = my_pool->queue_head;
if (!member) {
my_pool->queue_head = work;
} else {
while(member->next) {
member = member->next;
}
member->next = work;
}
/* 通知工作者线程,有新任务添加 */
pthread_cond_signal(&my_pool->queue_ready);
pthread_mutex_unlock(&my_pool->queue_lock);
return 0;
}
//测试代码
void *fun(void *arg)
{
printf("%d joker for smith",*(int*)arg);
return NULL;
}
int main()
{
if(pool_init(9)==NULL)
{
printf("create failed\n");
exit(1);
}
int i;
for(i=0;i<10;i++)
{
pool_add_work(fun, (void*)i);
}
pool_destroy();
return 0;
}
网上看了一篇线程池代码,弄了好多天才搞懂 特把自己作得注释贴上来
关于线程池结构以及互斥锁的运行机制
最新推荐文章于 2022-10-20 23:14:31 发布