操作系统——生产者-消费者问题
一、简单生产者-消费者问题
问题描述:一组生产者进程和一组消费者进程共享一个初始为空、大小为 n 的缓冲区,只有缓冲区没满时,生产者才能把消息放入到缓冲区,否则必须等待;只有缓冲区不为空时,消费者才能从中取出消息,否则必须等待。由于缓冲区是临界资源,它只允许一个生产者放入消息,或者一个消费者从中取出消息。
问题分析:
(1)关系分析。生产者和消费者对缓冲区互斥访问是互斥关系,同时生产者和消费者又是一个相互协作的关系,只有生产者生产后消费者才能消费,也是同步关系
(2)整理思路。只有生产者、消费者两个进程,且存在互斥和同步关系。所以需要解决的是互斥和同步 P V 操作的位置
(3)信号量设置。信号量 mutex 作为互斥信号量,用于控制互斥访问缓冲池,初值为 1 ;信号量 full 用于记录缓冲池中满缓冲区数,初值为 0 ;信号量 empty 用于记录缓冲池中空缓冲区数,初值为 n。
进程伪代码描述:
1 semaphore mutex = 1; // 临界区互斥信号量 2 semaphore empty = n; // 空闲缓冲区 3 semaphore full = 0; // 满缓冲区 4 5 producer() { 6 while(1){ 7 生产数据; 8 P(empty); 9 P(mutex); 10 将数据放入缓冲区; 11 V(mutex); 12 V(full); 13 } 14 } 15 16 Customer() { 17 while(1){ 18 P(full); 19 P(mutex); 20 将数据冲缓冲区取出; 21 V(mutex); 22 V(empty); 23 使用数据; 24 } 25 }
二、橘子-苹果问题
问题描述:桌子上有一只盘子,每次只能向其中放入一个水果。爸爸专向盘子中放苹果,妈妈专向盘子中放橘子,儿子专吃橘子,女儿专吃苹果。只要盘子为空,爸爸妈妈就可以向盘子中放一个水果;只有盘子中有想吃的水果时,儿子女儿才能取出一个水果吃
问题分析:
(1)关系分析:爸爸妈妈是互斥关系,临界资源为盘子;爸爸和女儿、妈妈和儿子是同步关系,且这两对进程必须连起来;儿子和女儿之间没有互斥同步关系。
(2)整理思路:可以抽象为两个生产者和两个消费者被连接到大小为 1 的缓冲区上。
(3)信号量设置:首先设置信号量 plate 为互斥信号量,初值为 1;信号 apple 为同步信号量,初值为 0;信号 orange 为同步信号量,初值为 0。
进程伪代码描述:
semaphore plate = 1; // 盘子 semaphore apple = 0; // 苹果 semaphore orange = 0; // 橘子 Father() { while(1){ 准备一个苹果; P(plate); 将苹果放入盘子中; V(apple); } } Mother() { while(1){ 准备一个橘子; P(plate); 将橘子放入盘子中; V(orange); } } Son() { while(1){ P(orange); 将橘子取出; V(plate); 吃橘子; } } Daughter() { while(1){ P(apple); 将苹果取出; V(plate); 吃苹果; } }