天天看点

【操作系统】生产者-消费者问题

生产者-消费者问题

生产者消费者问题(英语:Producer-consumer problem),也称有限缓冲问题(英语:Bounded-buffer problem),是一个多线程同步问题的经典案例。该问题描述了两个共享固定大小缓冲区的线程——即所谓的“生产者”和“消费者”——在实际运行时会发生的问题。生产者的主要作用是生成一定量的数据放到缓冲区中,然后重复此过程。与此同时,消费者也在缓冲区消耗这些数据。该问题的关键就是要保证生产者不会在缓冲区满时加入数据,消费者也不会在缓冲区中空时消耗数据。

要解决该问题,就必须让生产者在缓冲区满时休眠(要么干脆就放弃数据),等到下次消费者消耗缓冲区中的数据的时候,生产者才能被唤醒,开始往缓冲区添加数据。同样,也可以让消费者在缓冲区空时进入休眠,等到生产者往缓冲区添加数据之后,再唤醒消费者。通常采用进程间通信的方法解决该问题,常用的方法有信号灯法等。如果解决方法不够完善,则容易出现死锁的情况。出现死锁时,两个线程都会陷入休眠,等待对方唤醒自己。该问题也能被推广到多个生产者和消费者的情形。 —百度百科

问题分析

  • 只有缓冲区没满时,生产者才能把产品放入缓冲区,否则必须等待。
  • 只有缓冲区不空时,消费者才能从中取出产品,否则必须等待。
  • 缓冲区是临界资源,各进程必须互斥地访问。
【操作系统】生产者-消费者问题

缓冲区临界资源,互斥访问,一个进程访问,其他进程必须等待,缓冲区满或空与生产者/消费者关系如图:

【操作系统】生产者-消费者问题
semaphore mutex = 1; //互斥信号量,缓冲区的互斥访问
semaphore empty = n; //同步信号量,表示空闲缓冲区的数量
semaphore full = 0; //同步信号量,表示产品的数量

//生产者
producer() {
	while(1) {
		生产一个产品;
		P(empty);
		P(mutex);
		把产品放入缓冲区;
		V(mutex);
		V(full);
	}
}

//消费者
consumer() {
	while(1) {
		P(full);
		P(mutex);
		从缓冲区取出一个产品;
		V(mutex);
		V(empty);
		使用产品;
	}
}
           

多生产者-多消费者问题

和之前的生产者-消费者问题不同,这里的多生产者和多消费者是指多种类型的生产者和消费者,而不是指多个生产者、消费者。不同的生产者会生产不同的产品放入缓冲区,不同的消费者从缓冲区取不同的产品。

不同生产者和不同消费者存在互斥关系。

例如:我们看一个多生产者-多消费者常见的问题

桌子上有一只盘子,每次只能向其中放入一个水果。爸爸专向盘子中放苹果,妈妈专向盘子中放橘子,儿子专等着吃盘子中的橘子,女儿专等着吃盘子中的苹果。只有盘子空时,爸爸或妈妈才可向盘子中放一个水果。仅当盘子中有自己需要的水果时,儿子或女儿可以从盘子中取出水果。

【操作系统】生产者-消费者问题

爸爸和妈妈是不同类型的生产者,爸爸只生产苹果,妈妈只生产橘子,儿子和女儿是不同类型的消费者,儿子只吃橘子,女儿只吃苹果。

问题分析

爸爸放入苹果后,女儿才能取苹果

妈妈放入橘子后,儿子才能取橘子

只有盘子为空时,爸爸或妈妈才能放入水果

【操作系统】生产者-消费者问题
semaphore mutex = 1; //实现互斥访问盘子(缓冲区)
semaphore apple = 0; //盘子中有几个苹果
semaphore orange = 0; //盘子中有几个橘子
semaphore plate = 1; //盘子中还可以放多少个水果

dad() {
	while(1) {
		准备一个苹果;
		P(plate);
		P(mutex);
		把苹果放入盘子;
		V(mutex);
		V(apple);
	}
}

mom() {
	while(1) {
		准备一个橘子;
		P(plate);
		P(mutex);
		把橘子放入盘子;
		V(mutex);
		V(orange);
	}
}

daughter() {
	while(1) {
		P(apple);
		P(mutex);
		从盘中取出苹果;
		V(mutex);
		V(plate);
		吃掉苹果;
	}
}

son() {
	while(1) {
		P(orange);
		P(mutex);
		从盘中取出橘子;
		V(mutex);
		V(plate);
		吃掉橘子;
	}
}
           

其实:可以不用设置互斥访问盘子的互斥变量mutex,盘子容量为1,任何时刻,apple、orange、plate 三个同步信号量中最多只有一个是1。

【参考文献】

https://www.bilibili.com/video/BV1YE411D7nH?from=search&seid=9416521726351939812

继续阅读