进程之间是怎么协作的(信号量)

信号量机制(Semaphore):用来是实现进程/线程同步或者互斥的
有两种信号量执行方式:
整形信号量(自旋)和记录型信号量(阻塞队列方式)

整形信号量: 这里是引用声明一个变量S=1,表明可用资源数量为一个,有两个原语wait(等待)和signal(唤醒),进程A进来的时候,先调用wait方法,里面while循环判断可用资源是否小于等于0,小于等于0代表现在资源不够了,一直在原地自旋。
如果大于0说明还有足够的资源,执行后续的业务逻辑。
进程B执行完成之后,调用signal方法,唤醒,给资源S进行+1,说明现在可以有资源了,我执行完了,释放资源了,这个时候S=1
wait的自旋判断S(资源标记)是否小于等于0,由于进程B释放了资源,那么进程A可以执行后续的逻辑了,先执行S=S-1,表明自己占有了当前信号在执行了,S此时为0,其他进程会原地自旋,等待进程A执行完成

记录型信号量:
在这里插入图片描述
明天补,今天太晚了,要赶班车去了
本来打算16号接着继续吹,同步数据去了,上亿的数据同步是个问题,跑了一批数据还没同步完,后面月底继续跑一批

开始吹了:
首先我们定义一个记录型信号量(对象),里面有两个参数value(剩余资源数量,比如我们这里是1),process*L(进程等待队列,队列长度加入是无界队列)
当A和B两个进程都调用的时候
A进程进入了,先执行wait方法,进程等待,执行【value--】方法,此时变为了0,判断value是否小于0,不小于,执行后续逻辑

B进程也进入了,执行wait方法,进程等待,执行【value--】方法,此时变为了-1,判断是否小于0,小于,执行block方法,往进程等待队列里面加一个
A完成之后signal(唤醒),唤醒的时候【value++】,判断【value】是否小于等于0,此时加了之后为0,需要执行唤醒操作,B进程还在队列里面待得呢,注意这里唤醒的是进程等待队列中第一个等待的进程,接着挨个唤醒,直到唤醒全部进程(有多少等待的就循环调用多少次signal方法),直到value大于0
唤醒之后B进程接着执行wait,抢占资源,然后访问,唤醒。

问题:
1.调用wait方法和signal方法的时候,是否会存在CPU指令重排和其他进程指令插入进来交替执行,导致value值被改了多次的问题?
2.为什么要全部唤醒呢,只唤醒队列中第一个,然后执行一个唤醒一个,后面的挨个唤醒不就行了嘛?
3.有没有一个方法,可以全部唤醒呢,而不是调用多次

答案:
1.wait和signal都是原子性的
2.如果只唤醒第一个,只调用一次的话,还是A和B两个进程的例子,A执行完了,value改为了0,执行唤醒操作,B进程执行wait方法,会导致value--之后还是-1,小于0,一直在等待队列里面出不来了,那么肯定是要当剩余资源value>1的时候,才继续执行wait等一系列操作。
举例多个进程的情况,更好理解,比如ABC,三个进程的话,value为1,A执行变为0,B执行变-1,C执行变为-2,A跑完了,value++,value为0,执行唤醒B,还是上面那个结果,所以唤醒C,value++,value为1了,不需要唤醒了,B和C执行wait进行资源的争抢,B抢到了,value为0,C也抢,value为-1,C进等待队列,等B跑完,后面省略一万字
3.有,signalAll

内容来自bilibili站的mashibing,非本人整理,我只是把视频用文字描述了一下

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值