进程同步之熟睡的理发师问题

熟睡的理发师问题(The Sleeping-Baber Problem)是操作系统中关于进程同步的一个经典问题,它涉及了到临界区保护、锁、信号量等方面的知识。在这篇博客中,我将具体讲解这个问题并用pthread库编码解决,相关pthread库的使用可查阅IEEE官方文档,我是传送门~~~

问题描述:
 某个理发店有个瞌睡虫理发师,只要没有顾客,他就会去睡觉;而整个理发店由两个区域组成:有N把椅子的等候区和一把椅子的理发区。
 每当有一个顾客到来时,他有以下三种选择:
   1. 理发师在睡觉,则叫醒理发师并开始理发;
   2. 理发师在忙但等候区有空位,则进入等候区等候;
   3.理发师在忙而等候区又满了,则掉头离开;
 现在请你想一个办法帮助协调理发师和顾客。

要解决这个问题,我们先分析一下这个问题中将存在的一些的特殊情况:
 1. Deadlock:理发师给一个顾客理完发后没有人通知他后面还有顾客,于是理发师去睡觉而顾客一直等待,形成死锁;
 2. Starvation:要是某些顾客来的比较巧,刚好碰到理发师给一个顾客理完发,于是理发师连忙给新来的这个顾客理发而不顾忌等候区的顾客,可能造成等候区的顾客无限的等待下去;
 3. Critical Section:多个新来的顾客同时抢占椅子或同时又有一个顾客去理发,这便会涉及到椅子这个资源的分配问题,因此椅子便是这个问题的临界区资源。

 在解决Deadlock和Starvation问题时,我们可以通过维护两个信号量(顾客和理发师)来解决,;而Critical Section问题就使用一把互斥锁解决。

// 定义p、v操作
#define p(x) sem_wait(&x)
#define v(x) sem_post(&x)
// 初始化理发师和顾客信号量
sem_t baber, customers;
sem_init(&baber, 0, 1); // 理发师初始为1
sem_init(&customers, 0, 0)// 顾客初始为0
// 互斥信号量 保护临界区(即椅子)
pthread_mutex_t chair_mutex;


 所以理发师这边的逻辑大致如下:

p(customers);       // 查看顾客等候区(信号量),小于0就去睡觉(线程阻塞)

lock(chair_mutex);  // 顾客起身去理发,获得椅子读写的锁
++chair;            
unlock(chair_mutex);// 释放锁

// 给顾客理发...
v(baber);           // 理完一个,通知等候区的顾客自己已经空闲了

 而顾客的逻辑大致如下:

lock(chair_mutex);  // 刚到的顾客,获得椅子读写的锁,判断是否还有空位
if(chair > 0) {     // 有空位
    --chair;
    v(customers);   // 通知理发师队列有了新顾客
    unlock(chair_mutex);  // 释放锁
    p(baber);       // 等待理发师,阻塞线程
    // 理发...
    // 离开...
} else {            // 无空位  
    unlock(chair_mutex);  // 释放锁
    // 离开...
}

 通过实现以上这两种逻辑,使得理发师在每次睡觉之前将检查一下等候区是否还有顾客在等待(p(customer)),在给一个顾客理完发后又会通知等候区的顾客(v(baber));而每有新的顾客到来时,顾客又将通知理发师(v(customer)),然后去等候区队列的末尾等待理发师(p(baber));同时,使用互斥锁对椅子进行保护,防止了椅子被同时抢占造成资源的不同步。

  接下来给出设定一共有20个顾客先后来到,而只有5把椅子的运行结果(完整代码见末尾):

the baber shop opens...

customer #0 comes...
the chair left : 4
customer #0 is getting a hair cut...
the baber is working on one...
so the
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值