涉及到的知识点:
链表操作、互斥量、条件变量、线程
代码说明:
代码是在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\n", i, t);
pthread_cond_wait(&cond1, &mutex);
pthread_mutex_unlock(&mutex);
printf("p(%d)(%d)\n work", i, t);
continue;
}
insert_list(list, t);
printf("p(%d)(%d):%d\n", 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\n", i, t);
pthread_cond_wait(&cond2, &mutex);
pthread_mutex_unlock(&mutex);
printf("c(%d)(%d) work\n", i, t);
continue;
}
delete_list(list);
printf("c(%d)(%d):%d\n", 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();//阻塞,不让主函数结束
}