当前位置: 代码迷 >> 综合 >> 【考研】操作系统:2019年真题43(同步互斥问题)
  详细解决方案

【考研】操作系统:2019年真题43(同步互斥问题)

热度:124   发布时间:2023-09-22 20:34:51.0

 前言

解决同步互斥问题的思路,源于对王道讲解的总结笔记

同类型题目:

【考研】操作系统:2015年真题45(同步互斥问题)_住在阳光的心里的博客-CSDN博客

【考研】操作系统:2014年真题47(同步互斥问题)_住在阳光的心里的博客-CSDN博客

【考研】操作系统:2009年真题45(同步互斥问题)_住在阳光的心里的博客-CSDN博客

一、思路

解决同步互斥问题,思路步骤:

1. 分析各进程之间的同步互斥关系;

2. 设置互斥信号量 mutex = 1、同步信号量(一般设可使用的资源数为empty = N)。

3. 最好画出同步互斥关系图,并判断属于哪一种类型,如生产者-消费者问题、读者-写者问题、哲学家进餐问题、吸烟者问题。

二、题目

(建议先回顾经典的哲学家进餐问题:在本文最后)

43. 有 n (n >= 3) 位哲学家围坐在一张圆桌边,每位哲学家交替地就餐和思考。在圆桌中心有 m (m >= 1) 个碗,没两位哲学家之间有 1 根筷子。每位哲学家必须取到一个碗和两侧的筷子之后,才能就餐,进餐完毕,将碗和筷子放回原位,并继续思考。为使尽可能多的哲学家同时就餐,且防止出现死锁现象,请使用信号量的 P、V 操作(wait(), signal() 操作)描述上述过程中的互斥与同步,并说明所用信号量及初值的含义。

解:

传统的哲学家问题:

假设餐桌上有 n 个哲学家,n 根筷子。为避免死锁,限制至多 n - 1 个哲学家同时“抢”筷子,那么至多会有 1 个哲学家可以获得两根筷子并顺利进餐。

对于本题:n 位哲学家,n 根筷子,m 个碗。

利用碗这个限制资源来避免死锁:

(1)m < n, bowl = m;

碗的数量小于哲学家数量,此时最多允许 m 个哲学家进餐,确保不会出现所有哲学家都拿一侧筷子而无限等待另一侧筷子所造成死锁现象。

(2)m > n, bowl = n - 1;

碗的数量大于哲学家数量,此时保证最多只有 n - 1 个哲学家同时进餐。

所以 bowl = min{n-1, m};

再定义互斥信号量数组 chopsticks[n],利用 for 循环对 n 个数组元素赋值为1。

哲学家按顺序编号为 0 ~ n - 1,哲学家 i 左边筷子编号为 i,右边筷子编号为 (i + 1) % n。

完整代码:

//信号量 
semaphore bowl;   // 用于协调哲学家对碗的使用
semaphore chopsticks[n];  // 用于协调哲学家对筷子的使用for(int i = 0; i < n; i++)chopsticks[i].value = 1;  // 设置两个哲学家之间筷子的数量,或者用 chopsticks[i] = 1;bowl.value = min(n-1, m);  // bowl.value <= n-1,确保不死锁;或者用 bowl = min(n-1,m); CoBegin
Pi(){while(True){               //哲学家 i 的程序思考;P(bowl);        //取碗P(chopsticks[i]);      //取左边筷子P(chopsticks[(i + 1) MOD n]);       //取右边筷子就餐;V(chopsticks[i]);V(chopsticks[(i + 1) MOD n]);V(bowl);}
}
CoEnd

三、哲学家进餐问题

1、问题描述:五个哲学家共用一张圆桌,分别坐在周围的五张椅子上,在桌子上有五只筷子,他们的生活方式是交替地进行思考和进餐。平时,一个哲学家进行思考,饥饿时便试图取用其左右最靠近他的筷子,只有在他拿到两只筷子时才能进餐。进餐毕,放下筷子继续思考。请使用信号量的P、V操作(wait( )、 signal( )操作)描述上述过程中的互斥与同步,并说明所用信号量及初值的含义。

2、为避免死锁,有三种解决方法:

1)最多允许4位哲学家同时进餐

2)只有当一名哲学家左右两边筷子都可用时,才允许他抓起筷子。

3)偶数号哲学家先拿左边筷子,奇数号哲学家拿右边筷子

方法一:最多只允许四个哲学家同时进餐,以保证至少有一个哲学家能够进餐,最终总会释放出他所使用过的两支筷子,从而可使更多的哲学家进餐。 

定义信号量 count,只允许4个哲学家同时进餐,这样就能保证至少有一个哲学家可以就餐。

semaphore chopstick[5] = {1, 1, 1, 1, 1};  // 初始化信号量semaphore count = 4; // 设置一个count,最多有四个哲学家可以进来Pi(int i){while(true){思考;P(count);   // 请求进入房间进餐 当 count 为 0 时,不能允许哲学家再进来了P(chopstick[i]);   // 请求左手边的筷子P(chopstick[(i + 1) % 5]);   // 请求右手边的筷子进餐;V(chopstick[i]);   // 释放左手边的筷子V(chopstick[(i + 1) % 5]);   // 释放右手边的筷子V(count);   // 离开饭桌释放信号量}}

方法二:仅当哲学家的左右两支筷子都可用时,才允许他拿起筷子进餐。设置信号量 mutex 对取左边和右边筷子进行互斥操作。

semaphore mutex = 1;   // 设置取筷子的信号量
semaphore chopsticks[5] = {1, 1, 1, 1, 1};  // 初始化信号量Pi(){do{               //哲学家 i 的程序P(mutex);        // 在取筷子前获得互斥量P(chopsticks[i]);      //取左边筷子P(chopsticks[(i + 1) MOD 5]);       //取右边筷子V(mutex);  // 释放取筷子的信号量就餐;V(chopsticks[i]);  // 放回左边筷子V(chopsticks[(i + 1) MOD 5]);  // 放回右边筷子思考;}while(True);
}

方法三:规定奇数号的哲学家先拿起他左边的筷子,然后再去拿他右边的筷子;而偶数号的哲学家则先拿起他右边的筷子,然后再去拿他左边的筷子。按此规定,将是1、2号哲学家竞争1号筷子,3、4号哲学家竞争3号筷子。即五个哲学家都竞争奇数号筷子,获得后,再去竞争偶数号筷子,最后总会有一个哲学家能获得两支筷子而进餐。

semaphore chopstick[5] = {1, 1, 1, 1, 1};  // 初始化信号量Pi(int i){while(true){思考;if(i % 2 == 0){   // 偶数哲学家,先右后左。P(chopstick[(i + 1) % 5]) ;   // 取右边筷子P(chopstick[i]) ;   // 取左边筷子进餐;V(chopstick[(i + 1) % 5]) ;V(chopstick[i]) ;}else{   // 奇数哲学家,先左后右。P(chopstick[i]) ;   // 取左边筷子P(chopstick[(i + 1)%5]) ;    // 取右边筷子进餐;V(chopstick[i]) ;V(chopstick[(i + 1)%5]) ;}}
}

  相关解决方案