问题描述
系统中有一组生产者和一组消费者进程,生产者进程每次生产一个产品放入缓冲区,消费者进程每次从缓冲区取出一个产品。生产者和消费者共享一个初始为空,大小为n的缓冲区。只有缓冲区没满时,生产者才能把产品放入缓冲区,否则必须等待,只有缓冲区不空时,消费者才能取出产品,否则必须等待。缓冲区是临界资源,各进程必须互斥访问。
问题分析
1.找出题中描述的各个进程,确定他们之间的同步和互斥关系
进程有:生产者进程、消费者进程
同步关系(即一前一后执行):有两对,1.缓冲区满时,生产者必须等待消费者取走产品;2.缓冲区空时,消费者必须等待生产者生产产品
互斥关系:各个进程对缓冲区的访问
2.根据各个进程操作流程确定P,V操作的大致顺序
生产者每次要消耗§一个缓冲区,并生产(V)一个产品,消费者每次要消耗(P)一个产品并释放一个缓冲区;往缓冲区放入/取走产品要互斥
3.设置信号量。互斥信号量一般初始值为1,同步信号量根据对应资源数确定初始值
semaphore mutex = 1;//互斥信号量,实现对缓冲区的互斥访问
semaphore empty = n;//同步信号量,表示空闲缓冲区的数量
semaphore full = 0;//同步信号量,表示产品的数量
producer()
{
while(1)
{
P(empty);//消耗一个缓冲区
P(mutex);
把产品放入缓冲区;
V(mutex);//实现互斥是在同一进程中进行一对P,V操作
V(full);//增加一个产品
}
}
consumer()
{
while(1)
{
P(full);//消耗一个产品,实现同步是在其中一个进程执行P,另一进程执行V,前操作之后执行V,后操作之前执行P
P(mutex);
取走一个产品;
V(mutex);
V(empty);//增加一个缓冲区
}
}
思考:能否改变相邻P,V操作的顺序?
P操作不能,实现互斥的P操作必须在实现同步的P操作之后,否则可能发生死锁;对V操作可以交换顺序,但是会增加互斥操作的代码,从而延长占用临界资源的诗句,降低并发度。
多生产者-多消费者
问题描述
桌子上有一个盘子,每次只能放入一个水果,爸爸专门放苹果,妈妈放橘子,儿子专门吃橘子,女儿吃苹果。只有盘子为空时才能放水果,不空时吃水果,用P,V操作实现该过程。
1.找出题中描述的各个进程,确定他们之间的同步和互斥关系
进程有:生产者进程1(父)、生产者进程2(母),消费者进程1(儿),消费者进程2(女)
同步关系(即一前一后执行):有三对,1.只有盘子空时(由儿子或女儿触发),生产者才能放入水果;2.儿子必须等待母亲放橘子才能拿橘子;3.女儿必须等父亲放苹果才能拿苹果
互斥关系:各个进程对缓冲区(盘子)的访问
2.根据各个进程操作流程确定P,V操作的大致顺序
互斥:临界区前后分别P,V;同步:前V后P
3.设置信号量。互斥信号量一般初始值为1,同步信号量根据对应资源数确定初始值
semaphore mutex = 1;//实现互斥访问盘子
semaphore apple = 0;//盘子有几个苹果
semaphore orange = 0;//盘子有几个橘子
semaphore plate = 1;//盘子还能放几个水果
dad() mom() son() daughter()
{ { { {
while(1) while(1) while(1) while(1)
{ { { {
P(plate); P(plate); P(orange); P(plate);
P(mutex); P(mutex); P(mutex); P(mutex);
把苹果放入盘子; 把橘子放入盘子 取出一个橘子 取出一个苹果
V(mutex); V(mutex); V(mutex); V(mutex);
V(apple); V(orange); V(plate); V(plate);
} } } }
} } } }
思考:可以不用互斥信号量mutex吗?
答:刚开始,儿子、女儿进程即使上处理机运行也会被阻塞,所以考虑父进程先上处理机,则父亲P(plate),可以访问盘子→母亲P(plate),阻塞等待盘子→父亲V(apple)放入苹果,女儿进程被唤醒,因为其他进程即使运行也会被阻塞→女儿P(apple),V(plate),母亲进程被唤醒→母亲进程访问盘子,因为其他进程暂时无法进入临界区→…;故可以不用。原因在于在此例中盘子相当于大小为1的缓冲区,且apple,orange,plate三个同步信号量在同一时刻最多只有一个是1,所以任意时刻最多只有一个进程的P操作不会被阻塞并顺利进入临界区。若盘子容量为2的话则必须要互斥信号量。