进程同步与信号量

一.信号量的定义与简单应用

(1)什么是信号量

信号量是用来记录可用资源等待线程数目的一种特殊的整形变量通过对信号量的修改,使得各个进程得以有序推进,完成进程同步。

信号量的代码定义

struct semaphore {
   int value;//记录资源个数
   PCB *queue; //记录等待线程
}

两种基本操作

/*当进程申请消费资源时执行P函数。首先将资源数目value减一,然后判断value是否小于0。
如果小于0,则说明该进程尝试调用资源之前系统中资源数目已经为0了。这个时候该进程就将
进行休眠,进入等待状态*/
P(semaphore s) {
    s.value--;
    if(s.value < 0) {
         sleep(s.queue);
    }
}
/*当进程申请产生资源时执行V函数。将系统资源个数加一,判断value的值是否小于等于0(
如果value加一后仍然 <= 0,则说明原本的value一定是小于0的,也就意味着等待队列中存
在休眠进程。),如果满足,则唤醒等待队列中的消费者进程。*/
V(sempaphore s) {
    s.value++;
    if(s.value <= 0) {
         wakeup(s.queue);
    }
}

(2)信号量解决生产者-消费者问题

在这里插入图片描述

二.信号量临界区保护

(1)临界区保护原则

对于一些共享变量的访问和修改,我们需要保证它在同一时刻只被唯一一个进程访问修改。信号量就是这样的共享变量,包含这种变量的代码块叫做临界区

1.互斥进入:临界区中最多同时允许一个进程进入执行
2.有空让进:当临界区空闲时,如果此时存在进程等待进入临界区,则应该让该进程尽快进入。
3.有限等待:从进程发出进入请求到允许进入的时间必须是有限的,不能无限等待。

(2)临界区保护的三种策略

1.面包店算法

面包店算法体现了标记思想轮转思想的结合:每一个申请进入的进程都将按照从小到大的顺序获得一个大于0的序号,序号最小的优先执行,进程执行结束后修改序号为0,代表执行完毕。如果之后该进程又需要重新执行临界区代码,则需要重新取号排队等待
在这里插入图片描述

2.基于单核单CPU的阻止调度策略

回顾一下多进程调度产生安全问题的原因:当一个进程在对共享变量进行访问和修改时,恰好在这个过程中时间片用完了,该进程被迫中断,其他的进程被唤醒也进入了临界区。最终就可能会导致共享变量的数据错误。

为了解决这个问题,在单核单CPU系统中,我们可以在进程执行到临界区代码时阻止其余进程的调度,将临界区代码类似看作原子操作。具体而言就是在执行临界区代码前使用cli()函数(一个内嵌汇编函数)阻止调度,执行完毕后再使用sti()函数恢复正常调度。

3.基于硬件设计的原子保护策略

通过在临界区代码块加上锁来实现原子操作,从而实现了临界区代码保护。

关于锁的本质,其实也类似于信号量,可以视作一种特殊的整形变量,这也就意味着锁也需要得到其他变量的保护。如果这个工作交由程序来做,最终的结果就是套娃,子子孙孙,无穷尽也…因此,这里对于锁的保护是由硬件完成的

三.信号量的代码实现

…开学之后做实验任务时补上…

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值