【Linux】生產者消費者編程實現-線程池+訊號量

來源:互聯網
上載者:User

生產者消費者編程實現,採用了線程池以及訊號量技術。


線程的概念就不多說,首先說一下多線程的好處:多線程技術主要解決處理器單元內多個線程執行的問題,它可以顯著減少處理器單元的閑置時間,增加處理器單元的吞吐能力。

 

那麼為什麼又需要線程池呢?

 

我們知道應用程式建立一個對象,然後銷毀對象是很耗費資源的。建立線程,銷毀線程,也是如此。因此,我們就預先產生一些線程,等到我們使用的時候在進行調度,於是,一些"池化資源"技術就這樣的產生了。



一般一個簡單線程池至少包含下列組成部分。

1)        線程池管理器(ThreadPoolManager):用於建立並管理線程池

2)        背景工作執行緒(WorkThread): 線程池中線程

3)        任務介面(Task):每個任務必須實現的介面,以供背景工作執行緒調度任務的執行。

4)        任務隊列:用於存放沒有處理的任務。提供一種緩衝機制。

圖示:


圖1 線程池圖解


生產者消費者模型C語言代碼實現:

thread_pool_pv.h:

//線程池編程實現#ifndef THREAD_POOL_H#define THREAD_POOL_H#include <stdio.h>#include <stdlib.h>#include <semaphore.h>//訊號量sem_t#include <pthread.h>//任務介面,線程調用的函數typedef void* (*FUNC)(void *arg);//任務資料結構typedef struct thread_pool_job_s{        FUNC function;//線程調用的函數        void *arg;//函數參數        struct thread_pool_job_s *pre;//指向上一個節點        struct thread_pool_job_s *next;//指向下一個節點}thread_pool_job;//工作隊列typedef struct thread_pool_job_queue_s{        thread_pool_job *head;//隊列頭指標        thread_pool_job *tail;//隊列尾指標        int num;//任務數目        sem_t *quene_sem;//訊號量}thread_pool_job_queue;//線程池(存放消費者進程)typedef struct thread_pool_s{        pthread_t *threads;//線程        int threads_num;//線程數目        thread_pool_job_queue *job_queue;//指向工作隊列的指標}thread_pool;//typedef struct thread_data_s{//      pthread_mutex_t *mutex_t;//互斥量//      thread_pool *tp_p;//指向線程池的指標//}thread_data;//初始化線程池thread_pool* tp_init(int thread_num);//初始化工作隊列int tp_job_quene_init(thread_pool *tp);//向工作隊列中添加一個元素void tp_job_quene_add(thread_pool *tp,thread_pool_job *new_job);//向線程池中添加一個工作項目int tp_add_work(thread_pool *tp,void *(*func_p)(void *),void *arg);//取得工作隊列的最後個節點thread_pool_job* tp_get_lastjob(thread_pool *tp);//刪除工作隊列的最後個節點int tp_delete__lastjob(thread_pool *tp);//銷毀線程池void tp_destroy(thread_pool *tp);//消費者線程函數void* tp_thread_func(thread_pool *tp);//生產者線程執行函數void* thread_func_producer(thread_pool *tp);#endif



thread_pool_pv.c:

//線程池編程實現#include "thread_pool.h"//互斥量,用於對工作隊列的訪問pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;//標記線程池是否處於可用狀態static int tp_alive = 1;//初始化線程池thread_pool* tp_init(int thread_num){        thread_pool *tp;        int i;        if(thread_num < 1)                thread_num = 1;        tp = (thread_pool *)malloc(sizeof(thread_pool));        //判斷記憶體配置是否成功        if(NULL == tp){                printf("ERROR:allocate memory for thread_pool failed\n");                return NULL;        }        tp->threads_num = thread_num;        //分配線程所佔記憶體空間        tp->threads = (pthread_t*)malloc(thread_num * sizeof(pthread_t));        //判斷記憶體配置是否成功        if(NULL == tp->threads){                printf("ERROR:allocate memory for threads in thread pool failed\n");                return NULL;        }                if(tp_job_quene_init(tp))                return NULL;                tp->job_queue->quene_sem = (sem_t *)malloc(sizeof(sem_t));        sem_init(tp->job_queue->quene_sem,0,0);//訊號量初始化        //初始化線程        for(i = 0;i < thread_num;++i){                pthread_create(&(tp->threads[i]),NULL,(void *)tp_thread_func,(void *)tp);        }        return tp;}//初始化工作隊列int tp_job_quene_init(thread_pool *tp){        tp->job_queue = (thread_pool_job_queue *)malloc(sizeof(thread_pool_job_queue));        if(NULL == tp->job_queue){                return -1;        }        tp->job_queue->head = NULL;        tp->job_queue->tail = NULL;        tp->job_queue->num = 0;        return 0;}//線程函數void* tp_thread_func(thread_pool *tp){        FUNC function;        void *arg_buf;        thread_pool_job *job_p;        while(tp_alive){                //線程阻塞,等待訊號量                if(sem_wait(tp->job_queue->quene_sem)){                        printf("thread waiting for semaphore....\n");                        exit(1);                }                if(tp_alive){                        pthread_mutex_lock(&mutex);                        job_p = tp_get_lastjob(tp);                        if(NULL == job_p){                                pthread_mutex_unlock(&mutex);                                continue;                        }                        function = job_p->function;                        arg_buf = job_p->arg;                        if(tp_delete__lastjob(tp))                                return;                        pthread_mutex_unlock(&mutex);                        //運行指定的線程函數                        printf("consumer...get a job from job quene and run it!\n");                        function(arg_buf);                        free(job_p);                }                else                        return;        }        return;}//向工作隊列中添加一個元素void tp_job_quene_add(thread_pool *tp,thread_pool_job *new_job){        new_job->pre = NULL;        new_job->next = NULL;        thread_pool_job *old_head_job = tp->job_queue->head;        if(NULL == old_head_job){                tp->job_queue->head = new_job;                tp->job_queue->tail = new_job;        }        else{                old_head_job->pre = new_job;                new_job->next = old_head_job;                tp->job_queue->head = new_job;        }        ++(tp->job_queue->num);        sem_post(tp->job_queue->quene_sem);}//取得工作隊列的最後一個節點thread_pool_job* tp_get_lastjob(thread_pool *tp){        return tp->job_queue->tail;}//刪除工作隊列的最後個節點int tp_delete__lastjob(thread_pool *tp){        if(NULL == tp)                return -1;        thread_pool_job *last_job = tp->job_queue->tail;        if(0 == tp->job_queue->num){                return -1;        }        else if(1 == tp->job_queue->num){                tp->job_queue->head = NULL;                tp->job_queue->tail = NULL;        }        else{                last_job->pre->next = NULL;                tp->job_queue->tail = last_job->pre;        }        //修改相關變數        --(tp->job_queue->num);        return 0;}//向線程池中添加一個工作項目int tp_add_work(thread_pool *tp,void *(*func_p)(void *),void *arg){        thread_pool_job *new_job = (thread_pool_job *)malloc(sizeof(thread_pool_job));        if(NULL == new_job){                printf("ERROR:allocate memory for new job failed!\n");                exit(1);        }        new_job->function = func_p;        new_job->arg = arg;        pthread_mutex_lock(&mutex);        tp_job_quene_add(tp,new_job);        pthread_mutex_unlock(&mutex);}//銷毀線程池void tp_destroy(thread_pool *tp){        int i;        tp_alive = 0;                //等待線程運行結束        //sleep(10);        for(i = 0;i < tp->threads_num;++i){                pthread_join(tp->threads[i],NULL);        }        free(tp->threads);        if(sem_destroy(tp->job_queue->quene_sem)){                printf("ERROR:destroy semaphore failed!\n");        }        free(tp->job_queue->quene_sem);        //刪除job隊列        thread_pool_job *current_job = tp->job_queue->tail;        while(tp->job_queue->num){                tp->job_queue->tail = current_job->pre;                free(current_job);                current_job = tp->job_queue->tail;                --(tp->job_queue->num);        }        tp->job_queue->head = NULL;        tp->job_queue->tail = NULL;}//自訂線程執行函數void* thread_func1(){        printf("Task1 running...by Thread  :%u\n",(unsigned int)pthread_self());}//自訂線程執行函數void* thread_func2(){        printf("Task2 running...by Thread  :%u\n",(unsigned int)pthread_self());}//生產者線程執行函數void* thread_func_producer(thread_pool *tp){        while(1){                printf("producer...add a job(job1) to job quene!\n");                tp_add_work(tp,(void*)thread_func1,NULL);                sleep(1);                printf("producer...add a job(job2) to job quene!\n");                tp_add_work(tp,(void*)thread_func2,NULL);        }}int main(){        thread_pool *tp = tp_init(5);        int i;        int arg = 7;        pthread_t producer_thread_id;//生產者線程ID        pthread_create(&producer_thread_id,NULL,(void *)thread_func_producer,(void *)tp);        pthread_join(producer_thread_id,NULL);        tp_destroy(tp);        return 0;}


運行結果:



相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.