# 生产者 - 消费者问题
在进程同步中第一个问题就是生产者 - 消费者问题,首先我们利用记录型信号来分析这个问题。
好好好,我们直接伪代码解析!
解释在行代码的上方
//in 代表下一个要写入的位置,out 代表要读取的位置 | |
int in = 0,out = 0; | |
// 用于存储生产者生产的容器,可以理解为缓冲区 | |
item buffer[n]; | |
// 前两行不是重点,下面才是核心!! | |
//mutex 用于互斥访问共享资源,初值必须为 1(可以理解为锁) | |
//empty 代表中转的容量,初值为最大承载容量,题里会给(可以是各种容器) | |
//full 是生产出的一种逻辑 / 实体的物质 | |
// 总之不管是什么他是生产者生产出来的,一开始还没生产,full 初值为 0 | |
semaphore mutex = 1,empty = n,full = 0; | |
// 生产者逻辑 | |
void producer(){ | |
//do-while 死循环,不断生产,配合消费者模拟程序并发 | |
do{ | |
// 生产一个产品 | |
produce an item nextp; | |
... | |
//wait 什么什么就是什么什么 “--”,比如这里 wait (empty) 就是 empty-- | |
// 相当于空位置减一,申请一个缓冲区 | |
wait(empty); | |
// 相当于加锁,申请缓冲区的使用权 | |
wait(mutex); | |
// 将产品放入缓冲区之中 | |
buffer[in] = nextp; | |
// 下一个缓冲区的地址 | |
in = (in + 1) % n; | |
//signal 什么什么就是什么什么 “++”,比如这里 signal (mutex) 就是 empty++ | |
// 解锁,相当于释放权限 | |
signal(mutex); | |
// 生产的东西数量加 1,也就是释放缓冲区 | |
signal(full); | |
}while(true); | |
} | |
// 消费者逻辑 | |
void consumer(){ | |
//do-while 死循环,不断生消费,配合生产者模拟程序并发 | |
do{ | |
// 消费者要消费一个物质,将生产者的生产的 full-- | |
wait(full); | |
// 加锁,mutex-- | |
wait(mutex); | |
// 其实这里不用太深究,这里就是消费者从缓冲区拿走了一个生产者的生产的物质 | |
// 从缓冲区中取出产品 | |
nextc = buffer[out]; | |
// 导向下一个缓冲区的地址 | |
out = (out + 1) % n; | |
// 解锁,mutex++ | |
signal(mutex); | |
// 消费者已经取走了,空位置 empty++ | |
signal(empty); | |
// 消费者消费物质 | |
consume the item nextc; | |
... | |
}while(true) | |
} | |
void main(){ | |
cobegin | |
producer();consumer() | |
coend | |
} |
简单的写法:
Producer(): | |
Repeat | |
生产一个商品 | |
wait(empty); | |
wait(mutex); | |
将商品送至缓冲区; | |
signal(mutex); | |
signal(full); | |
Until false | |
Comsumer(): | |
Repeat | |
wait(full); | |
wait(mutex); | |
从缓冲区取走一个物品 | |
singal(mutex); | |
signal(empty); | |
Until false | |
Program main() | |
empty,full,mutex; | |
begin | |
empty = n; | |
full = 0; | |
mutex = 1; | |
cobegin | |
producer();consumer(); | |
coend | |
end |
# 练习一下!
桌上有个能盛得下五个水果的空子。爸爸不停地向盘中放苹果或橘子,儿子不停地从盘中取出桔子享用,女儿不停地从盘中取出苹果享用。规定三人不能同时从盘子中取放水果。使用信号量实现爸爸、儿子和女儿这三个循环进程之间的同步。
empty = 5,orange = 0,apple = 0,mutex = 1; | |
Dad(){ | |
while(1){ | |
wait(empty); | |
wait(mutex); | |
将水果放入盘中; | |
signal(mutex); | |
if(放了橘子) signal(orange); | |
else signal(apple); | |
} | |
} | |
Son(){ | |
while(1){ | |
wait(orange); | |
wait(mutex); | |
拿走一个桔子; | |
signal(mutex); | |
signal(empty); | |
吃桔子; | |
} | |
} | |
Daughter(){ | |
while(1){ | |
wait(apple); | |
wait(mutex); | |
拿一个苹果; | |
signal(mutex); | |
signal(empty); | |
吃苹果; | |
} | |
} |