生产者消费者问题
生产者消费者共享缓冲区,生产者向缓冲区中放数据,消费者从缓冲取中取数据,当缓冲区中被放满时,生产者进程就必须进入挂起状态,直到消费者从缓冲中取走数据时,生产者才能继续向缓冲区中存放数据,同样当缓冲取中没有数据时,消费者进程就必须进入挂起休眠状态,直到生产者向缓冲区中放入数据时,消费者才能被唤醒继续从缓冲区中取走数据。生产者消费者问题,也称有限缓冲问题,是一个多线程同步问题的经典案例。
实现目标
- 单生产者,单消费者
- 多生产者,多消费者
原理
生产者线程和消费者线程同时运行,当缓存区无数据(产品时)用pthread_cond_wait阻塞消费者,等待生产者产生一个数据(产品),利用rand()睡眠随机时间。主要原理为利用锁机制使生产者线程和消费者线程不能同时运行。
代码
单.c
/**********************************
* 一个生产者和一个消费者
* *******************************/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
struct Listnode{
int value;
struct Listnode *next;
};
struct Listnode *head = NULL;
pthread_mutex_t lock1;// = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond1; // = PTHREAD_COND_INITIALIZER;
void producter(void *arg)
{
while(1)
{
struct Listnode *p = malloc(sizeof(struct Listnode));
p->value = rand()%1000 + 1;
printf("producter——————————————————>%d\n", p->value);
pthread_mutex_lock(&lock1); //如果已经被加锁则阻塞等待解锁后加锁
p->next = head;
head = p;
pthread_mutex_unlock(&lock1); //解锁
pthread_cond_signal(&cond1); //如果消费者被pthread_cond_wait阻塞该行代码发送信号解除阻塞
sleep(rand() % 5); //睡眠随机时间
}
}
void consumer(void *arg)
{
while(1)
{
pthread_mutex_lock(&lock1); //如果已经被加锁则阻塞等待解锁后加锁
struct Listnode *q;
while(head == NULL)
{
pthread_cond_wait(&cond1, &lock1); //阻塞消费者线程,等待生产者生产产品
}
q = head;
printf("consumer--->%d\n",q->value);
head = q->next;
free(q);
pthread_mutex_unlock(&lock1);
sleep(rand() % 5); //睡眠随机时间
}
}
int main()
{
srand(time(NULL));
pthread_mutex_init(&lock1, NULL); //初始化互斥锁
pthread_cond_init(&cond1, NULL); //初始化条件变量
pthread_t pid, cid;
int ret;
ret = pthread_create(&pid, NULL, (void *)producter, NULL);
if(ret != 0)
{
printf("Error: pthread_create producter!\n");
}
ret = pthread_create(&cid, NULL, (void *)consumer, NULL);
if(ret != 0)
{
printf("Error: pthread_create consumer!\n");
}
pthread_join(pid, NULL); //等待生产者线程结束
pthread_join(cid, NULL); //等待消费者线程结束
pthread_mutex_destroy(&lock1); //销毁锁
pthread_cond_destroy(&cond1); //销毁条件变量
return 0;
}
多.c
/**********************************
* 多个生产者和多个消费者
* *******************************/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
struct Listnode{
int value;
struct Listnode *next;
};
struct Listnode *head = NULL;
pthread_mutex_t lock1;// = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond1; // = PTHREAD_COND_INITIALIZER;
void producter1(void *arg)
{
while(1)
{
struct Listnode *p = malloc(sizeof(struct Listnode));
p->value = rand()%1000 + 1;
printf("producter1——————————————————>%d\n", p->value);
pthread_mutex_lock(&lock1);
p->next = head;
head = p;
pthread_mutex_unlock(&lock1);
pthread_cond_signal(&cond1);
sleep(rand() % 5);
}
}
void producter2(void *arg)
{
while(1)
{
struct Listnode *p = malloc(sizeof(struct Listnode));
p->value = rand()%1000 + 1;
printf("producter2——————————————————>%d\n", p->value);
pthread_mutex_lock(&lock1);
p->next = head;
head = p;
pthread_mutex_unlock(&lock1);
pthread_cond_signal(&cond1);
sleep(rand() % 5);
}
}
void producter3(void *arg)
{
while(1)
{
struct Listnode *p = malloc(sizeof(struct Listnode));
p->value = rand()%1000 + 1;
printf("producter3——————————————————>%d\n", p->value);
pthread_mutex_lock(&lock1);
p->next = head;
head = p;
pthread_mutex_unlock(&lock1);
pthread_cond_signal(&cond1);
sleep(rand() % 5);
}
}
void consumer1(void *arg)
{
while(1)
{
pthread_mutex_lock(&lock1);
struct Listnode *q;
while(head == NULL)
{
pthread_cond_wait(&cond1, &lock1); //阻塞消费者线程,等待生产者生产产品
}
q = head;
printf("consumer1--->%d\n",q->value);
head = q->next;
free(q);
pthread_mutex_unlock(&lock1);
sleep(rand() % 5);
}
}
void consumer2(void *arg)
{
while(1)
{
pthread_mutex_lock(&lock1);
struct Listnode *q;
while(head == NULL)
{
pthread_cond_wait(&cond1, &lock1); //阻塞消费者线程,等待生产者生产产品
}
q = head;
printf("consumer2--->%d\n",q->value);
head = q->next;
free(q);
pthread_mutex_unlock(&lock1);
sleep(rand() % 5);
}
}
void consumer3(void *arg)
{
while(1)
{
pthread_mutex_lock(&lock1);
struct Listnode *q;
while(head == NULL)
{
pthread_cond_wait(&cond1, &lock1); //阻塞消费者线程,等待生产者生产产品
}
q = head;
printf("consumer3--->%d\n",q->value);
head = q->next;
free(q);
pthread_mutex_unlock(&lock1);
sleep(rand() % 5);
}
}
int main()
{
srand(time(NULL));
pthread_mutex_init(&lock1, NULL); //初始化互斥锁
pthread_cond_init(&cond1, NULL); //初始化条件变量
pthread_t pid, cid;
int ret;
ret = pthread_create(&pid, NULL, (void *)producter1, NULL);
if(ret != 0)
{
printf("Error: pthread_create producter!\n");
}
ret = pthread_create(&pid, NULL, (void *)producter2, NULL);
if(ret != 0)
{
printf("Error: pthread_create producter!\n");
}
ret = pthread_create(&pid, NULL, (void *)producter3, NULL);
if(ret != 0)
{
printf("Error: pthread_create producter!\n");
}
ret = pthread_create(&cid, NULL, (void *)consumer1, NULL);
if(ret != 0)
{
printf("Error: pthread_create consumer!\n");
}
ret = pthread_create(&cid, NULL, (void *)consumer2, NULL);
if(ret != 0)
{
printf("Error: pthread_create consumer!\n");
}
ret = pthread_create(&cid, NULL, (void *)consumer3, NULL);
if(ret != 0)
{
printf("Error: pthread_create consumer!\n");
}
pthread_join(pid, NULL);
pthread_join(cid, NULL);
pthread_mutex_destroy(&lock1);
pthread_cond_destroy(&cond1);
return 0;
}