Linux下实现生产者——消费者模型(代码)
涉及到的知识点:
链表操作、互斥量、条件变量、线程
代码说明:
代码是在Linux环境下运行,主要思路是在主函数中创建两个线程:生产者和消费者,将生产的产品保存在链表中。当没有产品时,消费者睡眠,直到被生产者唤醒,当产品达到20个,生产者睡眠,知道被消费者唤醒。
实例代码
#include<stdlib.h> #include<assert.h> #include<pthread.h> #include<stdio.h> #include<time.h> #include<unistd.h> typedef struct node{ //节点类型 int data; struct node *next; }NODE, *PNODE; typedef struct list//链表头 { PNODE front; PNODE rear; int num; }LIST, *PLIST; PLIST list; pthread_cond_t cond1 = PTHREAD_COND_INITIALIZER;//生产者的条件变量 pthread_cond_t cond2 = PTHREAD_COND_INITIALIZER;//消费者的条件变量 pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;//共用锁 //创建链表,带头结点 PLIST create_list(){ PNODE head = (PNODE)malloc(sizeof(NODE)); assert(head != NULL); PLIST list = (PLIST)malloc(sizeof(LIST)); head->next = NULL; list->front = head; list->rear = head; list->num = 0; return list; } //插入链表 void insert_list(PLIST list, int data){ if(list->num >= 20){ return; } PNODE pnew = (PNODE)malloc(sizeof(NODE)); assert(pnew != NULL); pnew->data = data; list->rear->next = pnew; list->rear = pnew; pnew->next = NULL; list->num++; } //删除一个节点 void delete_list(PLIST list){ if(list->num == 0){ return; } list->front->next = list->front->next->next; free(list->front->next); list->num--; //删除最后一个节点时,要特殊处理 if(list->num == 0){ list->rear = list->front; } } //生产者 void *producer(void *arg){ pthread_detach(pthread_self()); int t; int i = *(int *)arg; free(arg); while(1){ t =rand() % 4 +2;//随机2-5秒生产一个产品 sleep(t); pthread_mutex_lock(&mutex);//上锁 if(list->num == 20){ //产品有20个,生产者开始睡眠,直到被消费者唤醒 printf("p(%d)(%d) wait ", i, t); pthread_cond_wait(&cond1, &mutex); pthread_mutex_unlock(&mutex); printf("p(%d)(%d) work", i, t); continue; } insert_list(list, t); printf("p(%d)(%d):%d ", i, t, list->num); if(list->num > 5){ pthread_cond_broadcast(&cond2);//发送条件变量,唤醒全部消费者 } pthread_mutex_unlock(&mutex); } } //消费者 void *consumer(void *arg){ pthread_detach(pthread_self()); int i = *(int *)arg; int t; free(arg); while(1){ t = rand() %3 +1;//随机1-3秒消费一个产品 sleep(t); pthread_mutex_lock(&mutex);//上锁 if(list->num == 0){ //没有产品,消费者就睡眠,直到被唤醒 printf("c(%d)(%d) wait ", i, t); pthread_cond_wait(&cond2, &mutex); pthread_mutex_unlock(&mutex); printf("c(%d)(%d) work ", i, t); continue; } delete_list(list); printf("c(%d)(%d):%d ", i, t, list->num); if(list->num <= 15){ //如果小于15,唤醒全部生产者 pthread_cond_broadcast(&cond1);//发送条件变量,唤醒生产者 } pthread_mutex_unlock(&mutex);//解锁 } } int main(){ srand(time(NULL)); list = create_list(); pthread_t tid; //创建5个生产者 for(int i = 0; i < 5; i++){ int *p = (int *)malloc(sizeof(int)); *p = i; pthread_create(&tid, NULL, producer, p); } //创建3个消费者 for(int i = 0; i < 3; i++){ int *p = (int *)malloc(sizeof(int)); *p = i; pthread_create(&tid, NULL, consumer, p); } getchar();//阻塞,不让主函数结束 }