Linux下一个简单线程池实现的源码注释

本文详细解读了一段C语言在Linux环境下实现的线程池代码,通过注释帮助读者理解线程池的工作原理和设计细节,为后续的查阅和学习提供了便利。
摘要由CSDN通过智能技术生成

这里阅读了一份用C实现的线程池的设计,对其做了些注释,留作以后查看

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <pthread.h>
#include <assert.h>

/*任务结构体,构建成一个任务队列*/
typedef struct worker
{
    void *(*process)(void *arg);//真正具体要执行的任务的回调函数
    void *arg;                  //回调函数的参数
    struct worker *next;
}CThread_worker;

/*线程池结构体*/
typedef struct
{
    pthread_mutex_t queue_lock; //互斥锁
    pthread_cond_t  queue_ready;//条件变量

    CThread_worker *queue_head; //任务队列的头指针

    int shutdown;   //是否关闭线程池
    pthread_t *threadid;//指向每个线程的id

    int max_thread_num; //最大可创建的线程数量
    int cur_queue_size; //当前任务队列的大小,未执行的任务
}CThread_pool;

int pool_add_worker(void *(*process)(void *arg), void *arg);
void *thread_routine(void *arg);

/*定义一个全局指针变量,指向一个线程池,这样所以的线程都可以使用,要注意使用时加锁*/
static CThread_pool *pool = NULL;

/*初始化线程池*/
void pool_init(int max_thread_num)
{
    pool = (CThread_pool *)malloc(sizeof(CThread_pool));

    pthread_mutex_init(&(pool->queue_lock), NULL);
    pthread_cond_init(&(pool->queue_ready), NULL);

    pool->queue_head = NULL;

    pool->max_thread_num = max_thread_num;
    pool->cur_queue_size = 0;

    pool->shutdown = 0;

    pool->threadid = (pthread_t *)malloc(sizeof(pthread_t) * max_thread_num);
    int i = 0;
    /*创建max_thread_num个线程*/
    for(i=0; i < max_thread_num; i++)
    {
        pthread_create(&(pool->threadid[i]), NULL, thread_routine, NULL);
    }

}

/*向线程池中的任务队列添加任务*/
int pool_add_worker(void *(*process)(void *), void *arg)
{
    CThread_worker *newworker =
            (CThread_worker *)malloc(sizeof(CThread_worker));
    newworker->process = process;
    newworker->arg = arg;
    newworker->next = NULL;

    pthread_mutex_lock(&(pool->queue_lock));//要修改线程池,加锁防止有线程取出任务
    /*将任务加入到任务队列中*/
    CThread_worker *member = pool->queue_head;
    if(member != NULL)
    {
        while(member->next != NULL)
        {
            member = member->next;
        }
        member->next = newworker;
    }
    else
    {
        pool->queue_head = newworker;
    }

    assert(pool->queue_head != NULL);

    pool->cur_queue_size++;

    pthread_mutex_unlock(&(pool->queue_lock));
    /**唤醒一个空闲的线程,去执行该任务
      *如果此时所有线程都在忙碌,这句话没有任何作用
    **/
    pthread_cond_signal(&(pool->queue_ready));

    return 0;
}

/*销毁线程池
 *等待队列中的任务不再被执行,但是正在运行的线程会一直把任务完成后再退出
*/
int pool_destroy()
{
    if(pool->shutdown) //防止多次调用
        return -1;
    pool->shutdown = 1;//设置标志位,在thread_routine函数里会检测此标志位

    pthread_cond_broadcast(&(pool->queue_ready));//唤醒所有等待的线程

    int i;
    for(i=0; i < pool->max_thread_num; i++)
    {
        pthread_join(pool->threadid[i], NULL);//程序阻塞在这里,直到指定的线程退出
    }
    free(pool->threadid);

    CThread_worker *head = NULL;
    while(pool->queue_head != NULL)//销毁整个队列中的未执行的任务
    {
        head = pool->queue_head;
        pool->queue_head = pool->queue_head->next;
        free(head);
    }

    pthread_mutex_destroy(&(pool->queue_lock)); //销毁互斥锁
    pthread_cond_destroy(&(pool->queue_ready)); //销毁条件变量

    free(pool);//释放整个线程池
    pool = NULL;//好习惯

    return 0;
}

/*线程池中每个线程开始执行的地址*/
void *thread_routine(void *arg)
{
    printf("starting thread 0x%x\n", pthread_self());
    while(1)
    {
        pthread_mutex_lock(&(pool->queue_lock));

        /*任务队列中没有任务可执行,就阻塞该线程,直到被唤醒*/
        while(pool->cur_queue_size == 0 && !pool->shutdown)
        {
            printf("thread 0x%x is waiting\n", pthread_self());
            pthread_cond_wait(&(pool->queue_ready), &(pool->queue_lock));//该函数是原子操作,阻塞前解锁,被唤醒后加锁
        }

        if(pool->shutdown)//线程池要销毁则终止该线程
        {
            pthread_mutex_unlock(&(pool->queue_lock));
            printf("thread 0x%x will exit\n", pthread_self());
            pthread_exit(NULL); //线程终止函数,只能终止本线程
        }

        /*线程要取出队列中的一个任务,并执行它*/
        printf("thread 0x%x is starting to work\n", pthread_self());
        assert(pool->cur_queue_size != 0);
        assert(pool->queue_head != NULL);

        pool->cur_queue_size--;
        CThread_worker *worker = pool->queue_head;
        pool->queue_head = worker->next;
        pthread_mutex_unlock(&(pool->queue_lock));

        (*(worker->process))(worker->arg);//利用回调函数去执行任务
        free(worker);
        worker = NULL;
    }
    pthread_exit(NULL);//不可能被执行到
}

/*具体要执行的任务*/
void *myprocess(void *arg)
{
    printf("threadid is 0x%x, working on task %d\n", pthread_self(), *(int *)arg);
    sleep(1);
    return NULL;
}

int main(void)
{
    int i = 0;
    /*初始化线程池,这里创建了3个线程*/
    pool_init(3);

    /*创建10个任务,并加入到线程池的队列中去*/
    int *workingnum = (int *)malloc(sizeof(int) * 10);
    for(i=0; i < 10; i++)
    {
        workingnum[i] = i;
        pool_add_worker(myprocess, &workingnum[i]);
    }
    /*等待所有的任务都完成*/
    sleep(5);
    /*销毁线程池*/
    pool_destroy();

    free(workingnum);

    return 0;
}


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值