【操作系统】PV操作之上下楼梯问题,无饿死

问题描述

某教学楼楼梯较窄,为了安全规定课间,一旦有人从上往下走,则不允许任何人从下往上走,但此时可以允许多人同时往下走,反之依然。请应用所学的同步操作完成此问题,要求不会发生饥饿现象

版本一

思路:设置一个可通过楼梯的信号量,初始值为1(在这里信号量只有1,0两种状态,因此可看做锁)。楼梯上端为A,下端为B。下楼梯时在A处申请楼梯资源,如果楼梯空闲,则下楼梯,直到下楼梯状态完成到达B处,释放楼梯资源。上楼梯同理。

伪代码

Semaphore ok_to_enter = 1; 

PA
{
	enter_A 
	{ 
		P(ok_to_enter);
	 } 
	/* walk */ 
	enter_B 
	{ 
		V(ok_to_enter); 
	}
}

PB
{
	enter_B
	{ 
	 	P(ok_to_enter); 
  	} 
	 /* walk */ 
	enter_A
	{
  		V(ok_to_enter);
	}
}

存在的问题:只能单人通过楼梯,没有实现题目要求的可多人同时上或下楼梯的要求。

版本二

思路:在版本一基础上改进,可以参考读者写者问题的思路,设置两个变量,分别存储上下楼梯的人数,第一个下(上)楼梯的人申请楼梯资源,直到最后一个人完成下(上)楼梯操作才释放楼梯资源。这样就解决了多人同时上或下楼梯的需求。为了保证上下楼梯人数的正确,需加锁(mutexA、mutexB )来实现。
伪代码

Semaphore mutexA = mutexB = 1;
Semaphore bridge = 1; 
int countA = countB = 0;

PA 
{ 
 	P(mutexA); 
 	if(countA == 0) 
 	P(bridge); 
 	countA++;
 	V(mutexA); 
 	/* walk */ 
 	P(mutexA); 
 	countA--; 
 	if(countA == 0) 
 	V(bridge); 
 	V(mutexA); 
} 

PB
{ 
	P(mutexB); 
	if(countB == 0)
	P(bridge); 
	countB++; 
	V(mutexB); 
	/* walk */ 
	P(mutexB); 
	countB--; 
	if(countB == 0) 
	V(bridge); 
	V(mutexB); 
} 

存在的问题:可能会发生饿死现象。例如:下楼梯的人获取了楼梯资源,且一直持续不断有人下楼梯,那么等待上楼梯的人可能会“饿死”。

版本三

思路:为了不发生饿死的情况,在版本二上进行改进。变量含义在代码的注释中进行了说明,不再赘述。其思想是通过两个信号量来控制上下楼梯,满足条件(楼梯无人且上次通过的人与自己方向相反(或对面无人等待))的情况下获取上(下)楼梯的资源,完成上(下)楼梯的操作后,唤醒被阻塞的下(上)楼梯进程。(上下楼梯用的是同一个锁,所以会在pthread_mutex_lock(&m)处阻塞。 )由于定义变量记录了前一个人上下楼梯的方向,在判断能否获得楼梯资源时对此进行判断,如果与之方向相反就存在“优先级”,从而可以保证上下楼梯两边的人尽量平等的获取资源,不会出现一方的人一直霸占楼梯资源的现象。
代码:说明:pthread_condwait(),pthread_cond_signal()分别为P(),V()操作。

pthread_mutex_t  m; 
pthread_cond_t  turnA, turnB; //上下楼梯资源信号量
int waitingA, waitingB, AB_on_stair, BA_on_stair; //等待上、下楼梯人数,正在上、下楼梯人数
int pre = 0; //0表示A->B; 1表示B->A 

PA
{
	enter_A
	{ 
		pthread_mutex_lock(&m); 
		waitingA++; 
		while (BA_on_stair > 0 || prev == 0 && waitingB > 0))//判断条件
		pthread_condwait(&turnA, &m);//阻塞时会释放锁 
		waitingA--; 
		AB_on_stair++; 
		prev = 0; 
		pthread_mutex_unlock(&m); 
	} 
		/* walk */ 
	enter_B 
	{ 
		pthread_mutex_lock(&m); 
		AB_on_stair--; 
		pthread_cond_signal(&turnB); 
		pthread_mutex_unlock(&m); 
	}
}

PB
{
	enter_B 
	{ 
		pthread_mutex_lock(&m); 
		waitingB++; 
		while (AB_on_stair > 0 || prev == 1 && waitingA > 0)) 		     		
		pthread_cond_wait(&turnB, &m); 
		waitingB--; 
		BA_on_stair++; 
		prev = 1; 
		pthread_mutex_unlock(&m); 
	} 
	/* walk */ 
	enter_B 
	{ 
		pthread_mutex_lock(&m); 
		BA_on_stair--; 
		pthread_cond_signal(&turnA); 
		pthread_mutex_unlock(&m); 
	}
}

可能说的不是特别清楚,如果实在不能理解的话,可以代入一个实例结合代码就会比较容易理解。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值