生产者和消费者线程各创建5个。
商品队列使用的是带头结点链表,插入方式是头插法。
条件变量只创建1个,用于判断商品是否已空。因为使用链表保存,所以不用判断是否已满。
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#include <time.h>
//生产者消费者模型
//商品结点
struct node
{
int num;
struct node *next;
};
//声明一个指向链表的指针
struct node * head = NULL;
//创建一个互斥锁和条件变量
pthread_mutex_t mutex;
pthread_cond_t cond;
void * product(void *arg)
{
struct node *newnode = NULL;
while (1)
{
pthread_mutex_lock(&mutex);
newnode = (struct node *)malloc(sizeof(struct node));
newnode->num = rand()%100;
newnode->next = head->next;
head->next = newnode;
printf("生产者, id:%ld num:%d\n",pthread_self(),newnode->num);
pthread_mutex_unlock(&mutex);
pthread_cond_signal(&cond);
sleep(rand()%3);
}
return NULL;
}
void * consume(void *arg)
{
struct node *newnode = NULL;
while(1)
{
pthread_mutex_lock(&mutex);
while(head->next == NULL)
{
pthread_cond_wait(&cond,&mutex);
}
newnode = head->next;
printf("消费者, id:%ld num:%d\n",pthread_self(),newnode->num);
head->next = newnode->next;
free(newnode);
newnode = NULL;
pthread_mutex_unlock(&mutex);
sleep(rand()%3);
}
return NULL;
}
int main()
{
//创建链表头结点
head = (struct node *)malloc(sizeof(struct node));
head->next = NULL;
//初始化 锁和条件变量
pthread_mutex_init(&mutex,NULL);
pthread_cond_init(&cond,NULL);
srand((unsigned)time(NULL));
pthread_t t1[5],t2[5]; //t1 生产者,t2 消费者
//创建5个生产者线程
for(int i = 0; i < 5; i++)
{
pthread_create(&(t1[i]),NULL,product,NULL);
}
//创建5个消费者线程
for(int i = 0; i < 5; i++)
{
pthread_create(&(t2[i]),NULL,consume,NULL);
}
//线程等待
for(int i = 0; i < 5; i++)
{
pthread_join(t1[i],NULL);
pthread_join(t2[i],NULL);
}
//销毁锁和条件变量
pthread_mutex_destroy(&mutex);
pthread_cond_destroy(&cond);
return 0;
}
注意:这里条件变量的判断不能使用if,if只判断最初的一次,条件变量结束等待之后就不做判断了。但是消费者有5个。