消费者与生产者模型,以及用栈和队列实现

本文介绍了生产者-消费者模型的原理,通过栈和队列两种数据结构实现,利用pthread库中的互斥锁和条件变量解决线程间的同步问题。生产者线程在仓库满时等待,消费者线程在仓库空时等待,避免了生产过快或消费过快导致的问题。代码示例展示了如何在多线程环境中有效地控制数据生产和消费的流程。
摘要由CSDN通过智能技术生成

生产者与消费者模型

生产者:产生数据的进程或线程
消费者:使用数据的进程或线程

仓库:隔离生产者与消费者的缓冲区,与二者直连相比,避免了相互等待,提高了运行效率

问题1:生产快于消费,仓库满,生产者撑死。

生产者降低生产,通知消费,生产者线程进入睡眠叫醒睡眠的消费者线程
问题2:消费快于生产,仓库空,消费者饿死。
消费者降低消费,通知生产 消费者线程进入睡眠,叫醒睡眠的生产者线程

条件变量

可以让线程睡进去或者醒过来的一个容器,要与互斥锁配合使用

pthread_cond_t

int pthread_cond_init(pthread_cond_t *restrict cond,const pthread_condattr_t *restrict attr);
功能:初始化条件变量
    
int pthread_cond_signal(pthread_cond_t *cond);
功能:叫醒条件变量中的一个线程,并重新加锁互斥量,如果不能加,则进入阻塞状态

int pthread_cond_broadcast(pthread_cond_t *cond);
功能:叫醒条件变量中的所有线程,并重新加锁互斥量,如果不能加,则进入阻塞状态
    
int pthread_cond_wait(pthread_cond_t *restrict cond,pthread_mutex_t *restrict mutex);
功能:让当前线程睡入条件变量,并解锁一个互斥量
    
int pthread_cond_timedwait(pthread_cond_t *restrict cond,pthread_mutex_t *restrict mutex,const struct timespec *restrict abstime);
功能:让当前线睡入程条件变量一段时间并解锁互斥量,时间到后自动醒来并加锁互斥量
    
int pthread_cond_destroy(pthread_cond_t *cond);
功能:销毁条件变量

介绍完基础概念和函数直接上代码~

栈实现消费者生产者模型

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <unistd.h>
#include <pthread.h>
// 仓库容量
#define STORE_SIZE (20)
// 仓库
char store[STORE_SIZE];
// 数量
size_t store_cnt = 0;

pthread_mutex_t lock;
pthread_cond_t cond_empty;
pthread_cond_t cond_full;

void show_store(const char* who,const char* act,char data)
{
	printf("[");
	for(int i=0; i<store_cnt; i++)
	{
		printf("%c",store[i]);
	}
	printf("]%s%c : %s\n",act,data,who);
}

void* prun(void* arg)//生产者
{
	for(;;)
	{
		// 加锁
		pthread_mutex_lock(&lock);
		while(store_cnt >= STORE_SIZE)
		{
			// 此时仓库已满,生产者睡入仓库满的条件变量
			pthread_cond_wait(&cond_full,&lock);
		}

		// 生产数据
		char data = rand() % 26 + 'A';
		show_store("生产者","<-",data);
		store[store_cnt++] = data;
		usleep(rand()%30000);

		// 解锁
		pthread_mutex_unlock(&lock);
		
		// 叫醒所有睡入仓库空条件变量的线程
		pthread_cond_broadcast(&cond_empty);
	}
}

void* crun(void* arg)//消费者
{
	for(;;)
	{
		// 加锁
		pthread_mutex_lock(&lock);
		while(0 >= store_cnt)
		{
			// 此时仓库为空,生产者睡入仓库空的条件变量
			pthread_cond_wait(&cond_empty,&lock);	
		}

		// 消费数据
		char data = store[--store_cnt];
		show_store("消费者","->",data);
		usleep(rand()%30000);

		// 解锁
		pthread_mutex_unlock(&lock);

		// 叫醒所有睡入仓库满条件变量的线程
		pthread_cond_broadcast(&cond_full);
	}
}

int main()
{
	srand(time(NULL));
	// 初始化互斥量与条件变量
	pthread_mutex_init(&lock,NULL);
	pthread_cond_init(&cond_empty,NULL);
	pthread_cond_init(&cond_full,NULL);

	pthread_t tid[10];
	//创建生产者线程
	for(int i=0; i<5; i++)
	{
		if(i%2)
			pthread_create(&tid[i],NULL,prun,NULL);
		else
			pthread_create(&tid[i],NULL,crun,NULL);
	}

	// 等待所有线程结束
	for(int i=0; i<10; i++)
	{
		pthread_join(tid[i],NULL);
	}
}

队列实现消费者生产者模型

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <unistd.h>
#include <pthread.h>
// 仓库容量
#define STORE_SIZE (20)
// 仓库
char store[STORE_SIZE];
// 队头和队尾
int front = 0 , rear = 0;

pthread_mutex_t flock;
pthread_mutex_t rlock;
pthread_cond_t cond_empty;
pthread_cond_t cond_full;

void show_store(const char* who,const char* act,char data)
{
	printf("[");
	for(int i=front; i!=rear; i=(i+1)%STORE_SIZE)
	{
		printf("%c",store[i]);
	}
	printf("]%s%c : %s\n",act,data,who);
}

void* prun(void* arg)
{
	for(;;)
	{
		// 加锁
		pthread_mutex_lock(&flock);
		while((rear+1)%STORE_SIZE == front)
		{
			// 此时仓库已满,生产者睡入仓库满的条件变量
			pthread_cond_wait(&cond_full,&flock);
		}

		// 生产数据
		char data = rand() % 26 + 'A';
		show_store("生产者","<-",data);
		store[rear++] = data;
		rear %= STORE_SIZE; 
		usleep(rand()%500000);
		
		// 叫醒所有睡入仓库空条件变量的线程
		pthread_cond_broadcast(&cond_empty);

		// 解锁
		pthread_mutex_unlock(&flock);
	}
}

void* crun(void* arg)
{
	for(;;)
	{
		// 加锁
		pthread_mutex_lock(&rlock);
		while(front == rear)
		{
			// 此时仓库为空,生产者睡入仓库空的条件变量
			pthread_cond_wait(&cond_empty,&rlock);	
		}

		// 消费数据
		char data = store[front++];
		front %= STORE_SIZE;
		show_store("消费者","->",data);
		usleep(rand()%500000);

		// 叫醒所有睡入仓库满条件变量的线程
		pthread_cond_broadcast(&cond_full);

		// 解锁
		pthread_mutex_unlock(&rlock);
	}
}

int main()
{
	srand(time(NULL));
	// 初始化互斥量与条件变量
	pthread_mutex_init(&flock,NULL);
	pthread_mutex_init(&rlock,NULL);
	pthread_cond_init(&cond_empty,NULL);
	pthread_cond_init(&cond_full,NULL);

	pthread_t tid[10];
	//创建生产者线程
	for(int i=0; i<10; i++)
	{
		if(i%2)
			pthread_create(&tid[i],NULL,prun,NULL);
		else
			pthread_create(&tid[i],NULL,crun,NULL);
	}

	// 等待所有线程结束
	for(int i=0; i<10; i++)
	{
		pthread_join(tid[i],NULL);
	}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值