生产者-消费者模型
所谓生产者消费者模型,就是生产者和消费者共享一个有界缓冲池,生产者向其中投放产品,消费者从中取出产品消费。
生产者:我们定义一个设置空缓冲区个数的信号量empty,设置empty.value的初值为n;
消费者:我们定义一个放入产品的满缓冲区个数信号量full,设置full.value的初值为0.
我们需要为了给访问有界缓冲池定义一个信号量 mutex来保证任何时刻只有一个进程访问有界缓冲池。
//生产者部分代码
while(1)
{
product=produce();//产生产品
p(empty);//判断缓冲区是否有空的位置
p(mutex);//进入临界区
B[in]=product;//将产品投放到由in所指向的空缓冲区中。
in=(in+1)%n;//移向下一个空的缓冲区
V(mutex);
V(full);
}
while(1)
{
P(full);//请求一个缓冲区的产品
P(mutex);//进入临界区
product=B[out];//
out=(out+1)%n;
V(mutex);//退出临界区
V(empty);//空缓冲区的个数加1
consume();//消费
}
在生产者中:我们首先使用P(empty)判断是否由空的缓冲区,若没有则等待;若有则通过P(mutex)和V(mutex)原语方式进入临界区。由于投放产品使得缓冲区上的产品个数增加了1故我们将V(full)使得full.value+1,若此时有因为取不到产品得进程存在则调用full.L指向得阻塞得进程执行起来。消费者得分析过程类似。
哲学家进餐问题
描述:5个哲学家同坐在一张圆桌旁,每个人面前放着一碗面条,碗得俩旁各摆放着一只筷子。假设哲学家的生活除了吃饭就是思考问题,而吃饭的时候需要左右拿起左边的筷子,右手拿起右边的筷子然后开始进餐。吃饭之后再将筷子放回原处继续思考问题。
协调5为哲学家的活动过程,使得每个哲学家最终都可以进餐。
考虑下面俩种情况:
1,当所有哲学家同时拿起左手筷子时,则所有的哲学家都将拿不到右手筷子,并处于等待状态。都无法进餐,最终饿死。
2,同时拿起左手筷子,都拿不到右手的筷子。那么它们同时放下左手筷子。然后一直重复这个过程,最终饿死。
所以说普通的解法容易出现死锁。
我们可以采用一下方法中的一种来避免死锁的产生。
1,最多允许四位哲学家同时拿起左手的筷子。
mutex.value=4;
cobegin
while(1)
{
think();
P(mutex);
P(chopstick[i]);//拿起左手筷子
P(chopstick[(i+1)%5]);//拿起右手筷子
V(mutex);
eat();
V(chopstick[i]);//放回左手筷子
V(chopstick[(i+1)%5]);//放回右手筷子
}
2,仅当哲学家的左右俩支筷子都可用时,才允许他同时拿起左右的俩支筷子,否则一支也不拿。
使用AND同步机制(将进程需要的所有资源 一次性全部分配给该进程,只要有一个资源不能分配给该进程,则其他所有资源也不能分配给该进程 SP和SV为对应的信号量机制的P操作和V操作)
while(1)
{
think();
SP(chopstick[i],chopstick[(i+1)%5]);
eat();
SV(chopstick[i],chopstick[(i+1)%5]);
}
3,奇数号的哲学家先拿左手筷子,偶数号的筷子先拿右手筷子。