C++實現簡單生產者消費者模型__C++

來源:互聯網
上載者:User

      消費者/生產者模型是多線程編程開發的常用模型,該模型通過平衡生產者線程和消費者線程的工作能力來提高程式整體的資料處理能力。

       一般來說,我們的資源集區是有限的,訪問資源需要加鎖,訪問完以後需要解鎖,生產者需要在資源集區未滿的情況下才能生產產品,消費者需要在資源集區不空的情況下才能消費產品。且在設計時需要注意死結問題。

       下面採用semaphore,資源集區為環形緩衝區,來實現生產者消費者模型:    

#include <unistd.h>#include <errno.h>#include <pthread.h>#include <semaphore.h>#include <fcntl.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#define ERROR(func, no) { \        fprintf(stderr, "%s: %s\n", func, strerror(no)); \        exit(EXIT_FAILURE); \    }#define DEFAULT_CONSUMER_CNT    1#define DEFAULT_PRODUCER_CNT    3#define DEFAULT_BUFFER_SIZE 10static size_t in; //  producer's current posstatic size_t out; // consumer's current posstatic size_t consumer_id; // current product id for consumer static size_t producer_id; // current product id for producerstatic size_t consumer_cnt; // count of consumersstatic size_t producer_cnt; // count of producersstatic size_t buff_size; // resource buffer sizestatic int* g_buffer = NULL; // pointer to resource bufferstatic pthread_t* g_thread = NULL; // pointer to thread IDsstatic pthread_mutex_t g_mutex; //mutexstatic sem_t* g_sem_empty_ptr = NULL; // semaphore for consumerstatic sem_t* g_sem_full_ptr = NULL; // semaphore for producervoid* consume(void* arg) {    int id = *(int*)arg;    free(arg);    while(1) {        printf("Consumer[%d] waits buffer not empty\n", id);        sem_wait(g_sem_empty_ptr);        pthread_mutex_lock(&g_mutex);        int i, flag;        for(i=0; i<buff_size; ++i) {            printf("%2d:", i);            if(0 == g_buffer[i]) {                 printf(" nil");                if(out == i) {                    out = (out+1)%buff_size;                    printf("\n");                    flag = 1;                    continue;                }            } else {                printf(" %d", g_buffer[i]);            }            if(out == i) {                  printf("\t<-- consume[%d]", id);                flag = 0;            }            printf("\n");        }        if(0 == flag) {            consumer_id = g_buffer[out];            printf("Consumer[%d] begins consuming product %lu\n", id, consumer_id);            g_buffer[out] = 0;            out = (out+1)%buff_size;            printf("Consumer[%d] ends consuming product %lu\n", id, consumer_id);            pthread_mutex_unlock(&g_mutex);            sem_post(g_sem_full_ptr);        } else {            printf("*************No product to consume\n");             pthread_mutex_unlock(&g_mutex);        }        sleep(1);    }    return NULL;}void* produce(void* arg) {    int id = *(int*)arg;    free(arg);    while(1) {        printf("Producer[%d] waits buffer not full\n", id);        sem_wait(g_sem_full_ptr);        pthread_mutex_lock(&g_mutex);        int i, flag;        for(i=0; i<buff_size; ++i) {            printf("%2d:", i);            if(0 == g_buffer[i]) {                printf(" nil");            } else {                printf(" %d", g_buffer[i]);                if(in == i) {                    in = (in+1)%buff_size;                    printf("\n");                    flag = 1;                    continue;                }            }            if(in == i) {                printf("\t<-- produce[%d]", id);                flag = 0;            }            printf("\n");        }        if(0 == flag) {            g_buffer[in] = ++producer_id;            printf("Producer[%d] begins to produce product %lu\n", id, producer_id);            in = (in+1)%buff_size;            printf("Producer[%d] ends to produce product %lu\n", id, producer_id);            pthread_mutex_unlock(&g_mutex);            sem_post(g_sem_empty_ptr);        } else {            printf("*************No buffer to product\n");            pthread_mutex_unlock(&g_mutex);        }        sleep(1);    }    return NULL;}int main(int argc, char** argv){        consumer_cnt = DEFAULT_CONSUMER_CNT;        producer_cnt = DEFAULT_PRODUCER_CNT;    buff_size = DEFAULT_BUFFER_SIZE;        char* prog = argv[0];        int ch;         while ((ch = getopt(argc, argv, "b:c:p:")) != -1) {             switch (ch) {             case 'b':                     buff_size = atoi(optarg);                     //printf("-b option: %s\n", optarg);             case 'c':                     consumer_cnt = atoi(optarg);                     //printf("-c option: %s\n", optarg);                     break;             case 'p':                     producer_cnt = atoi(optarg);                     //printf("-p option: %s\n", optarg);                     break;             case '?':             default:                     printf("Usage: %s [-b buffersize] [-p producer_cnt] [-c consumer_cnt]\n"                                "\tdefault buffersize=10, producer_cnt=3, consumer_cnt=1\n", prog);                     exit(EXIT_FAILURE);             }           }    g_buffer = (int*)malloc(buff_size*sizeof(int));    g_thread = (pthread_t*)malloc((consumer_cnt+producer_cnt)*sizeof(pthread_t));    memset(g_buffer, 0, buff_size*sizeof(int));    memset(g_thread, 0, (consumer_cnt+producer_cnt)*sizeof(pthread_t));    g_sem_full_ptr = (sem_t*)malloc(sizeof(sem_t));    g_sem_empty_ptr = (sem_t*)malloc(sizeof(sem_t));    g_sem_full_ptr = sem_open("sem_producer", O_CREAT, 0, buff_size); //set semaphore full initially to the buffer length     g_sem_empty_ptr = sem_open("sem_consumer", O_CREAT, 0, 0); //set semaphore full initially to 0    pthread_mutex_init(&g_mutex, NULL);    int i, ret;    for(i=0; i<consumer_cnt; ++i) {        void *arg = malloc(sizeof(int));        memcpy(arg, &i, sizeof(int));        ret = pthread_create(&g_thread[i], NULL, consume, arg);        if(ret) {            ERROR("pthread_create", ret);        }    }    for(i=0; i<producer_cnt; ++i) {        void *arg = malloc(sizeof(int));        memcpy(arg, &i, sizeof(int));        ret = pthread_create(&g_thread[i+consumer_cnt], NULL, produce, arg);        if(ret) {            ERROR("pthread_create", ret);        }    }    for(i=0; i<consumer_cnt+producer_cnt; ++i) {        ret = pthread_join(g_thread[i], NULL);        if(ret) {            ERROR("pthread_join", ret);        }    }    sem_close(g_sem_full_ptr);    sem_close(g_sem_empty_ptr);    sem_unlink("sem_consumer");    sem_unlink("sem_producer");    pthread_mutex_destroy(&g_mutex);    free(g_buffer);    free(g_thread);    free(g_sem_full_ptr);    free(g_sem_empty_ptr);    exit(EXIT_SUCCESS);

       

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.