操作系统过桥问题

问题描述:

一条河上有N个桥墩组成的桥,过河的人只能沿着桥向前走而不能向后退,桥墩一次只能站一个人。过河时,只要对岸无人过,就可以过。但不允许河对岸的两个人同时过,以防止出现死锁。给出两个方向的人顺利过河的同步算法。


问题分析:

解决此问题之前,要先了解读者写者问题。

题意分析需要保证:

  1. 同一时刻两个方向只能有一个方向的人再前进。
  2. 只要方向1上还有人未通过,则方向2的人就不能上桥。
  3. 同一个方向上能有多个人等待过桥,但是每次只能过一个人,其他人可以排队。
  4. 方向2的人想上桥通过,必须等方向1的全部人都通过才可以。反之也成立。

通过上述分析我们不难发现,过桥问题实际就是读者写者的读者优先算法的一个变形。

  • 只能有一个方向的人过桥,等价于读者与写者只能有一种人在工作。通过互斥信号量解决二者之间的互斥关系。过桥问题通过mutex来实现两个方向上的互斥,mutex设置为1,表示将方向锁定。
  • 任意一个方向都有可能有很多人,所以设置count1/2变量来对每个方向上的人进行计数,只有第一个上桥的人才需要对方向上锁,最后一个离开桥的人对方向解锁。类比读者写者问题,只有第一个读者才需要对读写进程进行加锁,只有最后一个读者才对读写进程进行解锁。都是通过count变量来实现。
  • 依据双标志先检查法的不足,如果检查和上锁不是一气呵成的,则可能会违法忙则等待,同一时刻有多个进程进入临界区。因此必须设置一个互斥信号量来保证对检查和上锁一气呵成,因此出现了Scount1/2信号量,保证对对应的count变量的检查和上锁是一气呵成的。
  • 由于有n个桥墩,每个人只能站一个,因此最多允许一个方向上的N个人申请,所以共享变量Scount=N。 

此处不再区分到底是哪个方向优先问题,两个方向的优先级是通过哪一个先抢占处理机来决定的,并非人为决定。


代码:

Semaphore 
mutex=1,  //对方向锁定的互斥信号量
scount1=1, //确保方向1对count1的检查和上锁是原子操作
scount2=1, //确保方向2对count2的检查和上锁是原子操作
scount=N;  //一共有多少个桥墩
int 
count1=0, //1方向上有多少人
count2=0; //2方向上有多少人

//方向1
void direct1(int i)     
{
wait(scount1);
if(count1==0)  
     wait(mutex);
count1++;
signal(scount1);

wait(scount);         
上桥,过桥,下桥;
signal(scount);

wait(scount1);
count1--;
if(count1==0)
     signal(mutex);
signal(scount1);
}

//方向2
void direct2(int i)
{
wait(scount2);
if(count2==0)  
     wait(mutex);
count2++;
signal(scount2);

wait(scount);
上桥,过桥,下桥;
signal(scount);

wait(scount2);
count2--;
if(count2==0)
     signal(mutex);
signal(scount2);
}

//main执行
main()
{
   cobegin{
       direct1(1);
       …
       direct1(n);
       direct2(1);
       …
       direct2(m);
    }
}

猜你喜欢

转载自blog.csdn.net/weixin_60414376/article/details/129125934