https://www.cnblogs.com/caolicangzhu/p/7086176.html
本文主要来总结生产者-消费者模型的代码实现,至于其原理,请大家自行百度.
一、基于链表的生产-消费模型(条件变量)
我们以链表为例,生产者进行头部插入,消费者进行头部删除,因此,先将链表相关操作封装为LinkList.h,具体代码如下:
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 | //文件说明:LinkList.h//作者:高小调//创建时间:2017年06月27日 星期二 14时57分27秒//开发环境:Kali Linux/g++ v6.3.0#include<assert.h>#include<stdlib.h>#include<stdio.h>//链表节点typedefstructLinkListNode{    intval;    structinkListNode *next;}Node,*pNode,**ppNode;//初始化链表voidInitLinkList(ppNode head){    assert(head);    *head = NULL;}//判断链表是否为空intIsEmpty(pNode head){    returnhead==NULL;}//申请新节点pNode BuyNewNode(intval){    pNode ret = (pNode)malloc(sizeof(Node));    ret->val = val;    ret->next = NULL;    returnret;}//头插voidPushFront(ppNode head,intval){    assert(head);    if(*head==NULL){        *head = BuyNewNode(val);        return;    }    pNode newNode = BuyNewNode(val);    newNode->next = *head;    *head = newNode;}//头删voidPopFront(ppNode head,int*val){    assert(head);    if((*head) == NULL){        return;    }    if((*head)->next == NULL){        *val = (*head)->val;        free(*head);        *head = NULL;        return;    }    pNode del = *head;    *head = del->next;    *val = del->val;    free(del);}//销毁链表voidDestory(ppNode head){    assert(head);    pNode cur = *head;    pNode del = NULL;    while(cur!=NULL){        del = cur;        cur = cur->next;        free(del);    }    *head = NULL;}//打印链表voidPrintLinkList(pNode head){    pNode cur = head;    while(cur!=NULL){        printf("%d ",cur->val);        cur = cur->next;    }    printf("\n");} | 
然后进入我们线程的生产消费模型:
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 | //文件说明:test.c//作者:高小调//创建时间:2017年06月27日 星期二 14时56分13秒//开发环境:Kali Linux/g++ v6.3.0#include<stdio.h>#include<pthread.h>#include"LinkList.h"//互斥锁pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;//条件变量pthread_cond_t cond = PTHREAD_COND_INITIALIZER;//测试链表voidTestLinkList(){    pNode head;    InitLinkList(&head);    inttmp;    for(inti=0; i<10; ++i){        PushFront(&head,i);        PrintLinkList(head);    }    for(inti=0; i<10; ++i){        PopFront(&head,&tmp);        PrintLinkList(head);    }}pNode head;//生产者:每次向头节点插入数据void*Productor(void*arg){    intval = 0;    while(1){        //互斥锁加锁:确保生产时不会消费,消费时不会生产        pthread_mutex_lock(&lock);        val = rand()%100;        PushFront(&head,val);        printf("Productor push %d\n",val);        //互斥锁解锁        pthread_mutex_unlock(&lock);        //条件变量,生产完成之后向消费者发出信号消费        pthread_cond_signal(&cond);        sleep(1);    }}//消费者:每次将头节点数据取出void*Consumer(void*arg){    intval = 0;    while(1){        //互斥锁        pthread_mutex_lock(&lock);        while(head==NULL){            //链表中没数据,阻塞等待生产者发消费信号            printf("wait for data\n");            pthread_cond_wait(&cond,&lock);        }        PopFront(&head,&val);        printf("Consumer pop %d\n",val);        pthread_mutex_unlock(&lock);        sleep(1);    }}intmain(){    InitLinkList(&head);    pthread_t cid1,cid2;    pthread_create(&cid1,NULL,Productor,NULL);    pthread_create(&cid2,NULL,Consumer,NULL);    pthread_join(&cid1,NULL);    pthread_join(&cid2,NULL);        return0;} | 
二、基于环形队列的生产-消费模型(信号量)
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 | //文件说明:test2.c//作者:高小调//创建时间:2017年06月27日 星期二 16时29分30秒//开发环境:Kali Linux/g++ v6.3.0#include<stdio.h>#include<pthread.h>#include<semaphore.h>#include<stdlib.h>#define SIZE 1024//环形队列intarr[SIZE] = {0};sem_t sem_pro;      //描述环形队列中的空位置sem_t sem_con;      //描述唤醒队列中的数据//生产者,只要环形队列有空位,便不断生产void*productor(void*arg){    intdata = 0;    intproIndex = 0;    while(1){        //有空位便生产,没空位便阻塞等消费者消费        sem_wait(&sem_pro);        data = rand()%1234;        arr[proIndex] = data;        printf("product done %d\n",data);        proIndex = (proIndex+1)%SIZE;        //供消费者消费的数据加1        sem_post(&sem_con);    }}//消费者,只要环形队列中有数据,就不断消费void*consumer(void*arg){    intdata = 0;    intconIndex = 0;    while(1){        //环形队列中存在数据则消费,不存在数据则阻塞,直到有数据为止        sem_wait(&sem_con);        data = arr[conIndex];        printf("consume done %d\n",data);        conIndex = (conIndex+1)%SIZE;        //最后,消费了一个数据,空位加1        sem_post(&sem_pro);    }}intmain(){    pthread_t pro,con;    sem_init(&sem_pro,0,SIZE-1);        //一开始有很多空位置    sem_init(&sem_con,0,0);         //但并没有数据    pthread_create(&pro,NULL,productor,NULL);    pthread_create(&con,NULL,consumer,NULL);    pthread_join(pro,NULL);    pthread_join(con,NULL);    sem_destroy(&sem_pro);    sem_destroy(&sem_con);    return0;} |