Linux基于链表和循环队列的消费者生产者模型

3人阅读 评论(0) 收藏 举报

要模拟出消费者生产者模型,就要先了解他们之间的关系,生活中,我们在买东西时候就是一种生产者消费者模型,供货商就相当于生产者,而我们就是消费者,商店或者超市,就是一种可以促使我们与供货商之间进行交易的场所。

总结一下,我们可以简单的记为“321原则“。

  • 3是指三种关系,即为消费者与消费者的关系,消费者与生产者的关系,生产者与生产者的关系。
  • 2是指两个对象,即为消费者与生产者。
  • 1则是指一个交易场所。

既然我们知道有三种关系,那么我们就来仔细理一理这三种关系。

  • 消费者与消费者的关系。这个就理解为跟我们一样在超市买东西的人,我们去买同样的东西,假设数量不够的话,要么对方买,要么我们买,很明显是互斥关系
  • 生产者与消费者的关系。这个就理解为供货商和我们,只有在供货商有货供应的时候我们才能去买,不然我们是买不到的,所以这里肯定有同步的关系,而且在供货商送货物的这个过程中,我们是不能购买的,只有当他把货物放好后,我们才能进行购买,所以这里不仅有同步关系,也有互斥关系
  • 生产者与生产者的关系。这个就看作是不同供货商之间的关系,他们卖出同样的东西,但消费者必定只选一方进行消费,所以他们的关系就是互斥关系

清楚他们之间的关系后,我们就通过程序来进行模拟实现了。

#include<stdio.h>
#include<unistd.h>
#include<time.h>
#include<pthread.h>
#include<string.h>
#include<stdlib.h>
typedef struct node
{
	int num;
	struct node* next;
}node,*pnode,**ppnode;

pthread_mutex_t mutex;
pthread_cond_t cond;
pnode buynode(int n)
{
	pnode tmp = (pnode)malloc(sizeof(node));
	tmp->num = n;
	tmp->next=NULL;
	return tmp;
}
void listinit(ppnode head)
{
	pnode tmp = (pnode)malloc(sizeof(node));
	tmp->num = 0;
	tmp->next = NULL;
	*head = tmp;
}
void pushfront(pnode head,int m)
{
	int n  = m;
	pnode newhead = buynode(n);
	newhead->next=head->next;
	head->next=newhead;
}
void poplist(pnode head)
{
	if(head->next==NULL)
		perror("pop");
	pnode tmp = head->next;
	head->next=tmp->next;
	//free(tmp);
}
void *runC(void* arg)//消费者
{
	pnode head =* ((ppnode)arg);
	while(1)
		{
			pthread_mutex_lock(&mutex);
			while(head->next==NULL)
				{
					printf("consumer need waitting...\n");
					pthread_cond_wait(&cond,&mutex);
				}
			int d = head->next->num;
			printf("consumer get data:%d\n",d);
			poplist(head);
			//pthread_mutex_unlock(&mutex);
			sleep(2);
		}
}
void* runP(void* arg)//生产者
{
	pnode head= *((ppnode)arg);
	while(1)
	{
		sleep(2);
		int d = rand()%100+1;
		pushfront(head,d);
		printf("product data:%d\n",d);
		pthread_cond_signal(&cond);
		pthread_mutex_unlock(&mutex);
		sleep(2);
	}	
}
int main()
{	
	srand((unsigned long)time(NULL));
	pnode head = NULL;
	listinit(&head);
	pthread_mutex_init(&mutex,NULL);
	pthread_cond_init(&cond,NULL);	
	pthread_t p,c;
	
	pthread_create(&c,NULL,runC,&head);
	pthread_create(&p,NULL,runP,&head);
	
	pthread_join(c,NULL);
	pthread_join(p,NULL);	
	
	pthread_mutex_destroy(&mutex);
	pthread_cond_destroy(&cond);
	return 0;
}

通过结果我们不难看出他们之间的关系。这里就不在多说。

接下来我们要看的是环形队列实现生产者消费者模型,环形队列与链表不同的一点是如果生产者一直生产而消费者不消费的话,总有满的时候,一旦队列满了的话,生产者就不去消费了,同理,如果没有数据,消费者也不能去消费。

因此我们不难发现,在这里我们需要一个可以实现计数器功能的东西去协助我们进行数据量的和空白队列的表示,所以我们在这里就要了解一个东西,POSIX信号量。POSIX信号量可以用于进程也可以用于线程,由用户自己选择。

#include<semaphore.h>这是它需要引用的头文件。

信号量初始化函数:

int sem_init(sem_t* sem,int pshared,unsigned   int value);

          pshared:0表示线程间,1表示进程间。

          value:初始值。

销毁信号量:

int sem_destroy(sem_t* sem);

等待信号量:

int sem_wait(sem_t* sem);等待信号量,会将信号量减1;

发布信号量:

int sem_post(sem_t* sem);发布信号量,将信号量加1;

接下来我们就利用信号量来完成利用环形队列模拟的生产者消费者模型。

#include<stdio.h>
#include<stdlib.h>
#include<pthread.h>
#include<unistd.h>
#include<sys/types.h>
#include<semaphore.h>

int arr[6];
pthread_mutex_t lock1;
pthread_mutex_t lock2;
sem_t sem_data;
sem_t sem_blank;
void* runP(void* arg)//生产者
{
	static int i = 0;
	while(1)
	{
		pthread_mutex_lock(&lock1);
		sem_wait(&sem_data);
		int n = arr[i];
		printf("consumer get: %d\n",n);
		sem_post(&sem_blank);
		i++;
		i=i%6;
		pthread_mutex_unlock(&lock1);
		sleep(2);
	}
}
void* runC(void* arg)//消费者
{
	static int i = 0;
	while(1)
	{
		pthread_mutex_lock(&lock2);
		sem_wait(&sem_blank);
		int n = rand()%1000+1;
		arr[i]=n;
		printf("product data:%d\n",n);
		i++;
		i=i%6;
		sem_post(&sem_data);
		pthread_mutex_unlock(&lock2);
		sleep(2);
	}
}
int main()
{
	srand((unsigned long)time(NULL));
	pthread_t consumer[3];
	pthread_t product[3];
	pthread_mutex_init(&lock1,NULL);
	pthread_mutex_init(&lock2,NULL);
	sem_init(&sem_data,0,0);
	sem_init(&sem_blank,0,6);
	int i = 0;
	for(i=0;i<3;i++)
	{	pthread_create(&product[i],NULL,runC,NULL);}
	for(i=0;i<3;i++)
	{	pthread_create(&consumer[i],NULL,runP,NULL);}
	
	for(i=0;i<3;i++)
     {   pthread_join(consumer[i],NULL);}
	for(i=0;i<3;i++)
     {   pthread_join(product[i],NULL);}
	sem_destroy(&sem_data);
	sem_destroy(&sem_blank);
	pthread_mutex_destroy(&lock1);
	pthread_mutex_destroy(&lock2);
	return 0;
}

从结果我们也能证明代码的正确性。

查看评论

基于单链表和基于环形队列的生产者消费者模型

基于单链表和基于环形队列的生产者消费者模型
  • Yyingc
  • Yyingc
  • 2017-06-13 18:08:00
  • 459

循环队列 - 生产者与消费者模型

循环队列可以实现一个生产者与一个消费者模型, 不使用锁。   循环队列:size=10 生产者线程:不停地把从0递增的整数push到队列(尾部不存储,也就是最大存9个数),满了就等1s。 消费者线程:...
  • xiongli880612
  • xiongli880612
  • 2017-02-22 18:45:25
  • 365

linux c语言实现队列及用于生产者消费者模型

1.多线程模型 2.cpu调度下的xianchegn
  • songqqnew
  • songqqnew
  • 2014-10-20 14:24:02
  • 1954

[Linux]生产者与消费者 三种模型 C

“生产者/消费者”问题描述: 有一个有限缓冲区和两个线程:生产者和消费者。他们分别把产品放入缓冲区和从缓冲区中拿走产品。当一个生产者在缓冲区满时必须等待,当一个消费者在缓冲区空时也必须等待。 ...
  • z354681250
  • z354681250
  • 2016-06-09 23:25:07
  • 2307

Linux实现生产者消费者模型

生产者消费者模型 简单来说就是“321原则(并非某一规则,而是为了理解生产者消费者模型)” “3”代表的是三种关系 生产者与消费者的互斥与同步关系 生产者与生产者的互斥(或竞争)关系 消费...
  • double_happiness
  • double_happiness
  • 2017-06-01 11:35:03
  • 1656

生产者消费者模型(Linux系统下的两种实现方法)

生产者消费者问题是同步问题中的一种常见情况,借用一下维基百科的话 生产者消费者问题(英语:Producer-consumer problem),也称有限缓冲问题(英语:Bounded-buffer ...
  • yusiguyuan
  • yusiguyuan
  • 2015-09-07 14:32:19
  • 3624

LinuxC语言实现生产者和消费者模型

  • 2010年08月30日 11:14
  • 3KB
  • 下载

linux下用多进程同步方法解决生产者-消费者问题源代码

  • 2008年12月05日 22:37
  • 6KB
  • 下载

例说生产者和消费者模型

什么是生产者和消费者模型什么是生产者消费者模型?生产者和消费是操作系统中一种重要的模型,它描述的是一种等待和通知的机制,如下图。 生产者和消费者模型必须具有的条件用一句话概括,生产者消费者模型必...
  • bit_clearoff
  • bit_clearoff
  • 2017-02-19 17:14:29
  • 1990

互斥锁和条件变量(2)——生产者和消费者(发送消息,循环队列执行)

利用互斥锁和条件变量结合,实现生产者和消费者模型。其中生产者给消费者发送消息,发送字母字符串("a","b","c",...),消费者负责接收。 消息队列为循环队列。 队列为空时,消费者线程挂起,...
  • zhouzhenhe2008
  • zhouzhenhe2008
  • 2017-05-01 10:05:26
  • 250
    个人资料
    持之以恒
    等级:
    访问量: 1500
    积分: 297
    排名: 25万+
    文章分类
    最新评论