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

前言

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

同类型题目:

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

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

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

一、思路

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

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

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

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

二、题目

45. 有 A、B 两人通过信箱进行辩论,每个人都从自己的信箱中取得对方的问题。将答案和向对方提出的新问题组成一个邮件放入对方的邮箱中。假设 A 的信箱最多放 M 个邮件,B 的信箱最多 放 N 个邮件。初始时 A 的信箱中有 x 个邮件(0 < x < M),B 的信箱中有 y 个(0 < y < N)。辩论者每取出 一个邮件,邮件数减 1。A 和 B 两人的操作过程描述如下:

CoBegin

A{
    while(TRUE){
        从 A 的信箱中取出一个邮件; 
        回答问题并提出一个新问题; 
        将新邮件放入 B 的信箱;
    }
}

B{
    while(TRUE){
        从 B 的信箱中取出一个邮件; 
        回答问题并提出一个新问题; 
        将新邮件放入 A 的信箱;
    }
}
CoEnd

当信箱不为空时,辩论者才能从信箱中取邮件,否则等待。当信箱不满时,辩论者才能将新邮件放入信箱,否则等待。请添加必要的信号量和P、V(或 wait、signal)操作,以实现上述过程的同步。 要求写出完整过程,并说明信号量的含义和初值。

解:

(1)互斥资源:进程 A、B 对两个信箱的访问都是互斥的。有两个信箱,所以设置两个互斥信号量。mutex_A 和 mutex_B 分别用于对 A、B 信箱的互斥访问。

(2)同步问题:

A 信箱中有信时 A 才能取信,B 信箱中有信时 B 才能取信,设同步信号量 Full_A 、Full_B;

B 信箱中有空位时 A 才能放信,A 信箱中有空位时 B 才能放信,设同步信号量 empty_A、empty_B;

由于初始时 A 的信箱中有 x 个邮件(0 < x < M),B 的信箱中有 y 个(0 < y < N)

所以 Full_A = x、Full_B = y、empty_A = M - x、empty_B = N - y;

(3)A、B之间的同步互斥关系图如下:

(4) 伪代码如下:

semaphore mutex_A = 1;  // mutex_A 用于 A 的信箱互斥
semaphore mutex_B = 1;  // mutex_B 用于 B 的信箱互斥

semaphore Empty_A = M - x;  // empty_A 表示 A 信箱中还可存放的邮件数量
semaphore Full_A = x;  // Full_A 表示 A 信箱中的邮件数

semaphore Empty_B = N - y;  // empty_B 表示 B 信箱中还可存放的邮件数量
semaphore Full_B = x;  // Full_B 表示 B 信箱中的邮件数

分解步骤:一是先整互斥关系:

A(){  // 先使 A 和 B 互斥访问信箱
    while(TRUE){
        p(mutex_A);
        从A的信箱中取出一个邮件;
        v(mutex_A);
        
        回答问题竟提出新问题;
        
        p(mutex_B);
        将邮件放入B的信箱中;
        v(mutex_B);
        
    }
}
 
B() {
    while(TRUE){     
        p(mutex_B);
        从B的信箱中取出一个邮件;
        v(mutex_B);
 
        回答问题竟提出新问题;  
        
        p(mutex_A);
        将邮件放入A的信箱中;
        v(mutex_A);
        
    }
}

二是整同步关系:(分为两步)

第一步:从 A 取和往 A 放,从 B 取和往 B 放。

A(){  // 先使 A 和 B 互斥访问信箱
    while(TRUE){
        P(Full_A);  // 起初信箱 A 有 x 封邮件,对 A 取邮件,则改变 x 值

        p(mutex_A)
        从A的信箱中取出一个邮件;
        v(mutex_A)
        
        回答问题竟提出新问题;
        
        p(mutex_B)
        将邮件放入B的信箱中;
        v(mutex_B)
        
        V(Full_B);  // 往 B 信箱放邮件,则改变 y 值
    }
}
 
B() {
    while(TRUE){  
        P(Full_B);  // 起初信箱 B 有 y 封邮件,对 B 取邮件,则改变 y 值
   
        p(mutex_B)
        从B的信箱中取出一个邮件;
        v(mutex_B) 
 
        回答问题竟提出新问题;  
        
        p(mutex_A)
        将邮件放入A的信箱中;
        v(mutex_A)

        V(Full_A);  // 往 A 信箱放邮件,则改变 x 值
        
    }
}

第二步:判断此时 A、B 信箱内是否还可存放邮件

A(){  // 先使 A 和 B 互斥访问信箱
    while(TRUE){
        P(Full_A);  // 起初信箱 A 有 x 封邮件,对 A 取邮件,则改变 x 值

        p(mutex_A);
        从A的信箱中取出一个邮件;
        v(mutex_A);
        
        V(Empty_A);   // 从 A 中取出一个邮件后,A 的容量加一
        
        回答问题竟提出新问题;
        
        P(Empty_B);   // 判断此时 B 信箱内是否还可存放邮件
     
        p(mutex_B);
        将邮件放入B的信箱中;
        v(mutex_B);
        
        V(Full_B);  // 往 B 信箱放邮件,则改变 y 值
    }
}
 
B() {
    while(TRUE){  
        P(Full_B);  // 起初信箱 B 有 y 封邮件,对 B 取邮件,则改变 y 值
   
        p(mutex_B);
        从B的信箱中取出一个邮件;
        v(mutex_B);

        V(Empty_B);   // 从 B 中取出一个邮件后,B 的容量加一
 
        回答问题竟提出新问题;  

        P(Empty_A);  // 判断此时 A 信箱内是否还可存放邮件
        
        p(mutex_A);
        将邮件放入A的信箱中;
        v(mutex_A);

        V(Full_A);  // 往 A 信箱放邮件,则改变 x 值
        
    }
}

完整代码如下: 

semaphore mutex_A = 1;  // mutex_A 用于 A 的信箱互斥
semaphore mutex_B = 1;  // mutex_B 用于 B 的信箱互斥

semaphore Empty_A = M - x;  // empty_A 表示 A 信箱中还可存放的邮件数量
semaphore Full_A = x;  // Full_A 表示 A 信箱中的邮件数

semaphore Empty_B = N - y;  // empty_B 表示 B 信箱中还可存放的邮件数量
semaphore Full_B = x;  // Full_B 表示 B 信箱中的邮件数

A(){
    while(TRUE){
        p(Full_A);
        
        p(mutex_A);
        从A的信箱中取出一个邮件;
        v(mutex_A);
 
        v(Empty_A);
        
        回答问题竟提出新问题;
        
        p(Empty_B);
        
        p(mutex_B);
        将邮件放入B的信箱中;
        v(mutex_B);
        
        v(Full_B);
        
    }
}
 
B() {
    while(TRUE){
        p(Full_B);
        
        p(mutex_B);
        从B的信箱中取出一个邮件;
        v(mutex_B);
        
        v(Empty_B);
 
        回答问题竟提出新问题;
        
        p(Empty_A);
        
        p(mutex_A);
        将邮件放入A的信箱中;
        v(mutex_A);
        
        v(Full_A);
    }
}

另外一种解法(由评论区粉丝提供的思路编写而成)

semaphore numA = x;    //初始A信箱中信的数量 
semaphore numB = y;   //初始B信箱中信的数量
semaphore mutexA = 1;    //实现对A的互斥访问
semaphore mutexB = 1;   //实现对B的互斥访问

A(){
	while(true){
		p(mutexA);
		if(numA > 0){ 
            numA--;
			从A中取件;
        }
		V(mutexA);

		回答并提问;

		P(mutexB);
		if(numB < N){
            numB++;
			放入B中;
		}
		V(mutexB);
    }
}

B(){
	while(true){
		p(mutexB);
		if(numB>0){
            numB--;
			从B中取件;
		}
		V(mutexB);

		回答并提问;

		P(mutexA);
		if(numA < M){
            numA++;
			放入A中;
		}
		V(mutexA);
    }
}

评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

住在阳光的心里

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值