【操作系统】经典IPC问题——1 睡眠的理发师问题

碎碎念:明天考试,今晚答疑才发现还要考这个(听老师的意思这里会考写伪代码使用信号量PV操作和管程解决经典IPC问题),速速搞一下。
下面进入正文


0 问题描述

理发店里有一位理发师,一把理发椅和N把供等候理发的顾客坐的椅子

  • 如果没有顾客,则理发师便在理发椅上睡觉
  • 当一个顾客到来时,他必须先唤醒理发师
  • 如果顾客到来时理发师正在理发,则如果有空椅子,可坐下来等;否则离开

1 问题分析

先来分析一下涉及到的同步与互斥关系。

  • 理发师与顾客
    同步关系,理发师等待顾客来,顾客来了之后唤醒理发师。因此需要两个同步信号量。
  • 顾客与椅子
    互斥关系(竞争关系),因此需要互斥信号量来保证椅子数量准确。

2 解决方案

下面尝试用信号量(PV操作)和管程两种方式对问题进行解决。

2.1 PV操作

简单回顾一下PV操作,P操作是wait,同时对应-1;V操作是signal,同时对应+1。PV在同一个进程中为互斥信号量,分布在两个进程中为同步信号量。(很粗略的特征,但在实现时很好用)
因此,实现的伪代码如下:

semaphore customers = 0;
semaphore barbers = 0;
semaphore mutex = 1;
int waiting = 0;		//等待的顾客数
int chairs = N;		//总椅子数

process customer(){
	P(mutex);
	if(waiting < chairs){
		waiting++;
		V(customers);		//唤醒等待顾客的理发师
		V(mutex);
		P(barbers);		//等待理发师,有理发师则继续,没理发师则等待在该条件
		get_haircut();		//得到理发
	}
	else{
		V(mutex);
		leave();	//离开
	}
}

process barber(){
	while(true){
		P(customers);	//等待顾客,有顾客则继续执行,否则等待在该条件
		P(mutex);
		waiting--;
		V(barbers);	//通知等待在该条件的顾客可以理发了
		V(mutex);
		cut_hair();	//理发
	}
}

2.2 管程实现

其实管程就是对PV信号量的同一管理,即不需要再考虑互斥问题,管程自己有原子性,不可被中断。因此,只需要考虑wait和signal。管程中,进程会等待在条件变量上。本次实现设置了两个条件变量——barberscustomers,分别代表理发师已准备好(或者说是正在等待顾客的理发师),和顾客已准备好(等待理发师的顾客)。
对于顾客进理发店想要理发的过程即为:

  • 有无椅子,没有则离开,有则执行下一步
  • 等待人数加一
  • 唤醒正在等顾客的理发师barbers.signal()
  • 如果理发师在忙,则坐在椅子上等,成为等待理发师的顾客customers.wait()

对于理发师理发的过程:

  • 等待顾客barbers.wait()
  • 询问是否有顾客来了(即唤醒等待理发师的顾客)customers.signal()
  • 等待人数减一

最后两个线程分别调用管程中的函数即可。

伪代码如下:

Monitor Barbershop {
    int waiting = 0;
    int chairs = N;
    Condition barbers, costumers;

    void cuthair(){
        barbers.wait();   // 等待在理发师准备好的条件上
        customers.signal();   // 通知准备好的顾客。理发师已ok
        waiting--;          
    }

    void gethaircut(){
        if(waiting < chairs){
            waiting++;         
            barbers.signal(); // 唤醒理发师,通知等待在准备好理发师条件的理发师。顾客已来
            customers.wait();     // 如果理发师忙,等待在顾客准备好的条件上
        } else {
            // leave
        }
    }

}

void Barber() {
    while(true){
        // cut hair
        Barbershop.cuthair();
        cuthair();
    }
}

void Customer() {
    Barbershop.gethaircut();
    // get hair cut
    gethaircut();
}

以上即为睡眠的理发师的全部内容。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值