生产者-消费者 模型

一、相关概念:

同步和互斥是进程间很重要的交互模式,而生产者和消费者问题则是同步和互斥的一个经典模型。

同步是一种时序关系。如规定了进程1 处理完事情A后,进程2 才能处理事情 B,经典的同步问题是生产者和消费者间的同步。

互斥描述的是一种独占关系。如任一时刻,进城1 和进程2 中只能有一个写文件C。

生产者-消费者问题:

1、在同一个进程地址空间内执行的两个线程生产者线程生产物品,然后将物品放置在一个空缓冲区中供消费者线程消费。消费者线程从缓冲区中获得物品,然后释放缓冲区。当生产者线程生产物品时,如果没有空缓冲区可用,那么生产者线程必须等待消费者线程释放出一个空缓冲区。当消费者线程消费物品时,如果没有满的缓冲区,那么消费者线程将被阻塞,直到新的物品被生产出来。

2、生产者中先同步再互斥,而消费者先互斥再同步,或反之;以及生产者和消费者都先互斥再同步这几种情况都不会死锁,因为它们间并没有交叉关系,就更不可能形成死锁环。之所以先同步,再互斥,是为了更好的并发性:并发性的瓶颈是互斥区,先同步再互斥,使得互斥区代码更短。

二、单 生产者-消费者模型:

输入时,输入线程(插入等)是生产者,而计算线程是消费者;

输出时,计算线程(删除等)是生产者,而打印线程是消费者。

//链表:头进 尾出

#include<stdio.h>
#include<stdlib.h>
#include<pthread.h>

typedef int data_type;
typedef int* data_type_p;

typedef struct _node
{
	data_type data;
	struct _node *next;
}node_t,*node_p,**node_pp;

pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
node_p head=NULL;

static node_p buy_node(data_type _data)
{
	node_p tmp=malloc(sizeof(node_p));
	if(tmp)
	{
		tmp->data=_data;
		tmp->next=NULL;
		return tmp;
	}
	return NULL;
}
void init_list(node_pp _phead)
{
	*_phead=buy_node(0);
}

void delete_node(node_p tmp)
{
	if(tmp)
	{
		free(tmp);
		tmp=NULL;
	}
}
int pop_node(node_p list,data_type_p _data_p)
{
	if(list->next == NULL)
	{
		*_data_p=-1;
		return -1;
	}
	node_p tmp=list->next;
	list->next=tmp->next;
	*_data_p=tmp->data;
	delete_node(tmp);
	return 0;
}

void push_node(node_p list,data_type _data)
{
	node_p tmp=buy_node(_data);
	tmp->next=list;
	list->next=tmp;
}

void show_list(node_p list)
{
	node_p cur=list;
	while(cur)
	{
		printf("%d ",cur->data);
		fflush(stdout);
		cur=cur->next;
	}
}

void *product(void *arg)
{
	int i=0;
	while(1)
	{
		pthread_mutex_lock(&lock);
		printf("product data:%d\n",i++);
		push_node(head,i++);
		printf("product done ... wakeup consumer\n");
		pthread_mutex_unlock(&lock);
		pthread_cond_signal(&cond);
		sleep(1);
	}
}
void *consumer(void *arg)
{
	data_type _data;
	while(1)
	{
		pthread_mutex_lock(&lock);
		while(-1 == pop_node(head,&_data));
		{
			pthread_cond_wait(&cond,&lock);
		}
		printf("consumer data:%d\n",_data);
		pthread_mutex_unlock(&lock);
		sleep(1);
	}
}

int main()
{
        pthread_cond_t cond;
	pthread_cond_init(&cond,NULL);

	pthread_t tid1,tid2;
	pthread_create(&tid1,NULL,product,NULL);
	pthread_create(&tid2,NULL,consumer,NULL);
	pthread_join(tid1,NULL);
	pthread_join(tid2,NULL);
	pthread_cond_destroy(&cond);
	return 0;
}

//链表的更改:尾进 头出

    ... ...
int pop_node(node_p list,data_type_p _data_p)
{
	if(list->next == NULL)
	{
		*_data_p=-1;
		return -1;
	}
	node_p tmp=list;
	list=list->next;
	delete_node(tmp);
	return 0;
}
void push_node(node_p list,data_type _data)
{
        node_p tmp=buy_node(_data);
	while(list->next)
	{
		list=list->next;
	}
	list->next=tmp;
	tmp->data=_data;
	tmp->next=NULL;
}
    ... ...

三、多生产者-消费者模型:

// 其余代码见上 
int main()
{
        pthread_cond_t cond;
	pthread_cond_init(&cond,NULL);

	pthread_t tid1,tid2,tid3,tid4;
	pthread_create(&tid1,NULL,product,NULL);
	pthread_create(&tid2,NULL,product,NULL);
	pthread_create(&tid3,NULL,consumer,NULL);
	pthread_create(&tid4,NULL,consumer,NULL);
	pthread_join(tid1,NULL);
	pthread_join(tid2,NULL);
	pthread_join(tid3,NULL);
	pthread_join(tid4,NULL);
	pthread_cond_destroy(&cond);
	return 0;
}

注意 :生产者消费者问题,是同步和互斥的一个经典模型。但需要注意死锁问题,需要先同步再互斥。

时间: 2024-10-13 00:11:16

生产者-消费者 模型的相关文章

4.利用python生成器实现简单的“生产者消费者”模型

假如说,没有生成器这种对象,那么如何实现这种简单的"生产者消费者"模型呢? import time def producer(): pro_list = [] for i in range(10000): print "包子%s制作ing" %(i) time.sleep(0.5) pro_list.append("包子%s" %i) return pro_list def consumer(pro_list): for index,stuffe

生产者消费者模型实现多线程异步交互

[Python之旅]第六篇(五):生产者消费者模型实现多线程异步交互 消息队列 生产者消费者模型 多线程异步交互 摘要:  虽然标题是"生产者消费者模型实现多线程异步交互",但这里要说的应该还包括Python的消息队列,因为这里多线程异步交互是通过Python的消息队列来实现的,因此主要内容如下: 1 2 3 4 1.生产者消费者模型:厨师做包子与顾客吃包子 2.Python的消息队列 3.利用... 虽然标题是"生产者消费者模型实现多线程异步交互",但这里要说的应

‘生产者-消费者’模型与‘读-写者’模型

★生产者-消费者模型 首先,我们先分析一下生产者与消费者模型:生产者与消费者是模型中不可缺少的2种角色,当然模型中肯定需要一个保存数据的场所,能够将生产者生产的数据进行存储.同时,模型必须要满足生产者产生出数据后,消费者才能够进行使用,即就是消费者必须位于生产者之后,当然生产者生产的数据最多将场所放置满就不能继续生产,下面有简单的图示: 当然,如果有多个消费者和多个生产者,生产者与消费者之间的关系是同步的,生产者与生产者之间是互斥的,因为一块空间不能让多个生产者同时进行生产.消费者和消费者之间也

Java多线程之~~~~使用wait和notify实现生产者消费者模型

在多线程开发中,最经典的一个模型就是生产者消费者模型,他们有一个缓冲区,缓冲区有最大限制,当缓冲区满 的时候,生产者是不能将产品放入到缓冲区里面的,当然,当缓冲区是空的时候,消费者也不能从中拿出来产品,这就 涉及到了在多线程中的条件判断,java为了实现这些功能,提供了wait和notify方法,他们可以在线程不满足要求的时候 让线程让出来资源等待,当有资源的时候再notify他们让他们继续工作,下面我们用实际的代码来展示如何使用wait和 notify来实现生产者消费者这个经典的模型. 首先是

11.python并发入门(part8 基于线程队列实现生产者消费者模型)

一.什么是生产者消费者模型? 生产者就是生产数据的线程,消费者指的就是消费数据的线程. 在多线程开发过程中,生产者的速度比消费者的速度快,那么生产者就必须等待消费者把数据处理完,生产者才会产生新的数据,相对的,如果消费者处理数据的速度大于生产者,那么消费者就必须等待生产者. 为了解决这种问题,就有了生产者消费者模型. 生产者与消费者模型,是通过一个容器,来解决生产者和消费者之间的耦合性问题,生产者和消费者之间并不会直接通信,这样生产者就无需等待消费者处理完数据,生产者可以直接把数据扔给队列,这个

python--队列、生产者消费者模型

队列: import queue q = queue.Queue() #先入先出 print(q.empty()) #判断是否为空,空返回True q.put("d1") q.put("d2") q.put("d3") print(q.full()) #判断是否满,满返回True print(q.get()) #d1 print(q.get()) #d2 print(q.get()) #d3 print(q.get(timeout=1)) #阻塞

python2.0_s12_day9之day8遗留知识(queue队列&amp;生产者消费者模型)

4.线程 1.语法 2.join 3.线程锁之Lock\Rlock\信号量 4.将线程变为守护进程 5.Event事件 * 6.queue队列 * 7.生产者消费者模型 4.6 queue队列 queue非常有用,当信息必须安全的在多个线程之间进行数据交换的时候就应该想到queue 所以,queue它能保证数据被安全的在多个线程之间进行交换,那他就是天生的线程安全. queue有那么几种: class queue.Queue(maxsize=0) # 先入先出 class queue.LifoQ

生产者/消费者模型

http://www.cnblogs.com/xrq730/p/4855663.html 什么是生产者/消费者模型 一种重要的模型,基于等待/通知机制.生产者/消费者模型描述的是有一块缓冲区作为仓库,生产者可将产品放入仓库,消费者可以从仓库中取出产品,生产者/消费者模型关注的是以下几个点: 1.生产者生产的时候消费者不能消费 2.消费者消费的时候生产者不能生产 3.缓冲区空时消费者不能消费 4.缓冲区空时生产者不能生产 生产者/模型作为一种重要的模型,它的优点在于: 1.解耦.因为多了一个缓冲区

OpenMP实现生产者消费者模型

生产者消费者模型已经很古老了吧,最近写了个OpenMP版的此模型之实现,来分享下. 先说一下模型的大致做法是: 1.生产者需要取任务,生产产品. 2.消费者需要取产品,消费产品. 生产者在生产某个产品之后,要告知消费者此产品已经可以使用了.消费者通过获得可以使用这个信号来取得产品,进一步消费产品. 比如,我们有N个图像需要对每一个图像作滤波或者变换等处理,并且把处理后的结果存到硬盘上. 那么生产者可以将N个图像看成N个任务,每个任务都是独立的,每个任务的计算结果可以看成是产品,消费者就是取这个产

java生产者消费者模型

import java.util.Queue;import java.util.concurrent.LinkedBlockingQueue; public class Consumer extends Thread {    private String product;    private Queue<String> storeHouse = new LinkedBlockingQueue<String>();        public Consumer(){