L16 & L17 进程同步与信号量 & 信号量临界区保护

进程推进的合理有序同步——信号量
等待是进程同步的核心
信号量的出现是对于如果有多个P的时候,只有信号是不能唤醒所有生产者的,只能唤醒一个生产者

  • 信号只能唤醒一个生产者

信号量小于0对应的是有多少个进程睡眠了

  • 要学会等待(观察信号量是否为负,如果是负数就需要等待)

是很重要的


  • 用临界区来保护信号量
  • 用信号量来支持进程的同步

信号量(整型变量)

互斥


让进程之间的合作变得合理有序
实现这个的依据是信号量
想象一个司机售票员的例子,司机要启动车辆,这个时候应该让售票员先关门,然后发一个信号,然后司机可以启动车辆,我们说司机是在等待一个信号
同理,司机停车了,就需要发送一个信号给售票员,然后售票员才能开门

图片.png

等待就是阻塞,这个也是进程同步的核心。

比如说生产者--消费者模型,当缓冲区满的时候,就要停下来,不然会溢出。如果缓冲区空了,就不敢再消费了,已经没有东西可以消费了。

图片.png


引出信号量

之前的信号在程序里面的体现是counter,信号表示的只是,它只能唤醒一个进程,然后就无效了,如果有n个进程,那么剩下的n - 1个进程就会一直sleep下去。所以我们需要一个量——信号量来表示有多少个进程在睡眠,唤醒的时候需要唤醒多少个进程。

信号量——记录有多少个进程睡眠了

如果只有信号的话,只能是发信号还有等信号,对应的是唤醒睡眠

图片.png

如果有了信号量的话,我们用sem来表示,根据sem是多少来决定是唤醒还是睡眠,如果sem已经小于0了,那就睡眠,然后消费者进程看到sem小于0了,就会去唤醒。

这样子就实现了进程的走走停停

图片.png
图片.png

习题

图片.png

P操作和V操作

  • P操作对应的是消费者
  • V操作对应的是生产者
    睡眠和唤醒对应的是都是信号量是否会小于0

P和V的2段代码

图片.png

生产者在共享缓冲区的时候,消费者不能进去
消费者在共享缓冲区的时候,生产者不能进去

实现这一点是需要靠互斥信号量来实现

为什么要保护信号量

因为多个进程会共同修改信号量,这样会导致信号量的语义错误。这种错误就称为——

调度有关的共享数据语义错误

什么是临界区?

假如A进程有段代码,B进程有段代码,他们俩都有一个小部分的代码涉及到了相同的信号量,那么这一小部分就是临界区,临界区的执行是一个原子操作——一个进程进去后修改完才能解锁。

临界区是成对or成组出现的

互斥——不能同时进入

死锁预防就是2个方法

  • 一次性申请所有资源
  • 按序等待

死锁避免

找到一个安全序列(通过银行家算法

图片.png

死锁避免的代价太大了

因为每一个进程Pi每次申请的时候,都要进行一次银行家算法,看是否会引起死锁,时间复杂度太高

图片.png

图片.png

死锁检测和恢复

发现问题,检测到问题用的还是银行家算法,不过执行的次数少了一些了。
恢复的时候采用的是进程回滚,回滚到一定程度了看看是否还会死锁。

但是选择谁回滚,和实现回滚都比较麻烦。

图片.png

死锁忽略的方法

图片.png

图片.png

死锁

多个进程由于互相等待对方持有的资源,从而导致任何一个进程都无法执行的情况。

死锁的成因

  • 互斥——一个资源被A进程占用后,其他进程无法使用
  • A进程占有了资源后,不释放,还要去申请其他的资源

好比已经占有了一条路,还要继续前进到其他的道路

  • 环路等待——每个进程占有的资源和想要申请的资源形成了一个环路

相当于每辆公交车已经有了自己的车道,还想要去占别人的车道,但是别人不让,所以就僵持住了。

死锁的4个必要条件

  • 互斥使用
  • 不可抢占——资源只能进程自己放弃,比如公交车自己开走

上面2点都是资源的固有属性

  • 请求和保持——进程已经有了一个资源还不释放,同时去申请其他的资源
  • 循环等待


    图片.png

死锁本身的出现就是一个小概率事件

你可能感兴趣的:(L16 & L17 进程同步与信号量 & 信号量临界区保护)