经典同步问题
1. 生产者——消费者问题
问题描述:一组生产者进程和一组消费者进程共享一个初始为空、大小为
n
的缓冲区,只有缓冲区没满时,生产者才能把消息放入缓冲区,否则必须等待;只有缓冲区不空时,消费者才能从中取出消息,否则必须等待。由于缓冲区是临界资源,它只允许一个生产者放入消息,或一个消费者从中取出消息。
问题分析
1. 分析关系
-
同步关系:
-
互斥关系:
2. 整理思路
- 同步关系的P、V操作:
- 互斥关系的P、V操作:
3. 信号量初值设置
- 同步信号量:
信号量full
用于记录当前缓冲池中的“满”缓冲区数,初值为0
。
信号量empty
用于记录当前缓冲池中的“空”缓冲区数,初值为n
。 - 互斥信号量:
信号量mutex
作为互斥信号量,用于控制互斥访问缓冲池,互斥信号量初值为1
;
代码
semaphore mutex=l; //临界区互斥信号量
semaphore einpty=n; //空闲缓冲区
semaphore full=0; //缓冲区初始化为空
producer(){ //生产者进程
while(1){
produce an item in nextp; //生产数据
P (empty);(要用什么,P—下) //获取空缓冲区单元
P (mutex);(互斥夹紧) //进入临界区
add nextp to buffer;(行为) //将数据放入缓冲区
V (mutex);(互斥夹紧) //离开临界区,释放互斥信号量
V(full);(提供什么,V—下) //满缓冲区数加1
}
}
consumer(){ //消费者进程
while (1){
P(full); //获取满缓冲区单元
P(mutex); //进入临界区
remove an item from buffer; //从缓冲区中取出数据
V(mutex); //离开临界区,释放互斥信号量
V(empty); //空缓冲区数加1
consume the item; //消费数据
}
}
同步和互斥的顺序能否调换顺序?
类比:
2. 多生产者——消费者问题
问题描述:桌子上有一个盘子,每次只能向其中放入一个水果。爸爸专向盘子中放苹果,妈妈专向盘子中放橘子,儿子专等吃盘子中的橘子,女儿专等吃盘子中的苹果。只有盘子为空时,爸爸或妈妈才可向盘子中放一个水果;仅当盘子中有自己需要的水果时,儿子或女儿可以从盘子中取岀。
问题分析
1. 分析关系
- 同步关系
- 互斥关系
这里有4个进程,实际上可抽象为两个生产者和两个消费者被连接到大小为1的缓冲区上。
2. 信号量设置
- 同步信号量
信号量apple
表示盘子中是否有苹果,初值为0
表示盘子为空,不许取,apple=1
表示可以取。
信号量orange
表示盘子中是否有橘子,初值为0
表示盘子为空,不许取,orange=1
表示可以取。 - 互斥信号量
信号量plate
,表示是否允许向盘子放入水果,初值为1
表示允许放入,且只允许放入一个。
代码
加互斥信号量的代码(推荐)
semaphore plate=1,apple=0,orange=0;
dad(){ //父亲进程
while(1){
prepare an apple;
P(plate); //互斥向盘中取、放水果
P(mutex);
put the apple on the plate; //向盘中放苹果
V(mutex);
V(apple); //允许取苹果
}
}
mom(){ //母亲进程
while(1){
prepare an orange;
P(plate); //互斥向盘中取、放水果
P(mutex);
put the orange on the plate; //向盘中放橘子
V(mutex);
V(orange); //允许取橘子
}
}
son () { //儿子进程
while(1){
P (orange); //互斥向盘中取橘子
P(mutex);
take an orange from the plate;
V(mutex);
V (plate); //允许向盘中取、放水果
eat the orange;
}
}
daughter (){ //女儿进程
while (1){
P (apple); //互斥向盘中取苹果
P(mutex);
take an apple from the plate;
V(mutex);
V (plate); //允许向盘中取、放水果
eat the apple;
}
}
不加上互斥信号量的代码
semaphore plate=1,apple=0,orange=0;
dad(){ //父亲进程
while(1){
prepare an apple;
P(plate); //互斥向盘中取、放水果
put the apple on the plate; //向盘中放苹果
V(apple); //允许取苹果
}
}
mom(){ //母亲进程
while(1){
prepare an orange;
P(plate); //互斥向盘中取、放水果
put the orange on the plate; //向盘中放橘子
V(orange); //允许取橘子
}
}
son () { //儿子进程
while(1){
P (orange); //互斥向盘中取橘子
take an orange from the plate;
V (plate); //允许向盘中取、放水果
eat the orange;
}
}
daughter (){ //女儿进程
while (1){
P (apple); //互斥向盘中取苹果
take an apple from the plate;
V (plate); //允许向盘中取、放水果
eat the apple;
}
}
参考资料
《王道:23操作系统考研复习指导》