题17

题目

【2009 统考真题】三个进程 互斥使用一个包含 个单元的缓冲区。
每次用 produce() 生成一个正整数并用 put() 送入缓冲区某一空单元;
每次用 getodd() 从该缓冲区中取出一个奇数并用 countodd() 统计奇数个数;
每次用 geteven() 从该缓冲区中取出一个偶数并用 counteven() 统计偶数个数。
请用信号量机制实现这三个进程的同步与互斥活动, 并说明所定义的信号量的含义 (要求用伪代码描述)。

分析


三个进程维护三个资源,一个是总量empty,一个是奇数odd,一个是偶数even,这三个资源的初始值分别是N00
这三个资源都在同一个缓冲区里面调度的,这个缓冲区是互斥的,上一把锁,作为门槛,也就是mutex
现在资源就定义好了,需要记住的是,每次先拿锁开门,然后再看自己需要的资源是否有空,如果有空缺,才使用,用完了,唤醒其他的进程使用资源,然后把锁还回去
在生产者-消费者模型中,释放资源和释放锁这两个动作是可以颠倒的,因为缓冲区才是真正的那个互斥的门槛

semaphore mutex = 1 , empty = n, odd = 0 , even = 0;
 
//P1是生产者,每次访问缓冲区,给empty填充内容
P1() {
	while(1) {
		//获取自己的资源,检查是否有空缺
		P(empty); //如果有空缺,需要生产,上锁,自己生产
		P(mutex); //上锁
		//开始生产正整数
		int non = produce();
		put(non);
		// 把生产的资源放出来,让其他进程可以使用
		if(non % 2 == 0) {
			V(even);
		} else {
			V(odd);
		}
		//最后,活儿干完了,解锁缓冲区
		V(mutex);
	}
}
 
//P2是消费者,先拿缓冲区的锁,然后再去P自己的资源能不能用,如果可以的话,就消费它,把空缺位置释放出来,最后再把锁还回去,关门
P2() {
	while(1) {
		P(odd); //如果能拿到,上锁消费
		P(mutex); //上锁
		//开始消费奇数
		getodd();
		int odd_non = countodd();
		// 把空缺位释放出来
		V(empty);
		//活儿干完了,上锁
		V(mutex);
	}
}
 
P3() {
	while(1) {
		P(even);
		P(mutex);
		//开始消费偶数
		geteven();
		int even_non = counteven();
		V(mutex);
		//V操作可以颠倒
		V(empty);
	}
}