之前写了操作系统的文章,然后最近发现有什么不足,仔细检查,发现没有写PV操作,那么我们接下来单独为PV操作写博客,让大家不要害怕PV操作,我们深入分析,大家
在学习PV操作之前,先理解两个基本概念吧。
同步、互斥:
同步:与其说是“同步”,不如说是“合作”。 我们的目标只有一个。 我们朝着同一个目标奔跑,是在大家的努力下一起完成这样的事情的。 还很容易理解吧。 也不一定太难了。
互斥:借用别人的话“千军万马过独木桥”,用非常易懂的语言来表达我们的概念。 例如,有一支大部队来到独木桥,却要排好队,一个个来; 其实,在现实生活中,还有一个很好的例子可以解释这个互斥的概念。 例如,打印机、打印机这些工具非常好地体现了互斥的概念。 打印机被别人占有的话,就不会有那种混乱,不管多着急,也只能等待了。
其实借用别人的语言、资料和工具,让我们的学习更轻松,给我们的学习添油加醋,享受什么呢? 这就是我说的“站在巨人的肩膀上”,看问题的话,很多问题会变得轻松。 这是一种以给我们的学习添油加醋为目的的思想。 这是题外话,更重要的是思想,值得学习。
接下来也请看同步的图:
这张图给人的印象也很具体。 具体来看这张图吧。 A仓库里有货物。 然后,你需要把货物运到b仓库。 运输商甲和运输商乙完成这个过程。 他们的目标只有一个,就是把货物从a移动到b,一起朝着这个方向发展,所以说这是同步的问题。
关键资源:是刚才提到的互斥,需要通过打印机、光驱等互斥方式共享资源。
关键部分:进程访问关键资源的代码。
说了那么久,我们才引入了PV操作,这个PV操作还是很有趣的。
视点操作:解决互斥和同步问题。 视点操作是分开出现的:
p动作: S=S-1。 如果S=0,则进程继续。 否则,进程将被放入队列。
v操作:设S=S 1,S0时,启动队列中的一个进程。
我不太明白这样理解。 让我们看一个例子。
接下来,我们来看看非常适合我们生活的问题。 生产者——消费者问题:
8pt; font-family:arial; font-size:13pt"> 我们还是一样,通过图片来分析问题:
这是一个著名的同步问题,虽然生产者进程和消费者进程都是异步方式运行的,但它们之间必须保持同步,即不允许消费者进程到一个空缓冲区去取产品,也不允许生产者进程向一个已装满产品且尚未被取走的缓冲区中投放产品。这是一个单缓冲区情况。那么这个单缓冲区的PV操作,应该是怎样的呢?我们来看看:
我们分析分析,很容易的发现这个流程,前提是S1初值为1,S2初值为0。我们需要记住P操作减1,V操作加1,然后这个分析就变得易如反掌了,我们先对初值进行一下说明:
a、我们把S1的初值设为1:是说明缓冲区还有一个空间可以使用,对于生产者而言,每一个缓冲区的一个空间就是一个资源,也就是说,一开始运行的时候,就允许生产者投放一个产品到缓冲区,
b、然后投放到缓冲区之后,我们来看消费者进程,P(S2):首先我们要进程一个判断,判断缓冲区中是否有产品,对消费者而言,缓冲区中有产品,就代表有一个资源可以使用,但是最初状态那个缓冲区中是没有资源的,所以S2的初值应该是为0的。
我们刚才都提到了资源的问题,就是信号量的一个值应该是表示资源的数量,但是就消费者和生产者而言,对于他们的资源是不同的,概念是不同的,生产者:缓冲区有多少个空格,就有多少个资源;而对消费者来说,缓冲区有多少个满的格,就有多少个资源,是刚好是相反,所以说,就是这么相反,所以当消费者从缓冲区取出一个产品之后,对于生产者而已,就多了一个资源。
其实这个过程就是这样的。
1、生产者:P(S1),那么P(S1),S1=S1-1,得到P(S1=0)这个进程还能进行,那么生产者把一个产品投放到缓冲区。
2、V(S2),S2=S2+1,S2初值为0,所以S2=S2+1>0,那么就激活了P(S2),那么消费者就能取出一个产品。
4、消费产品:消费产品之前,还有一个V(S1),就激活了P(S1),让生产者继续投放产品到缓冲区。
特别简单吧,这是单缓冲区分析。
我们接下来看一个相对来说,有点复杂一点点的,多缓冲区的,其实也一样一样的,继续:
我们还是分析一样的问题,生产者、消费者问题:
对应的PV操作应该是这样的:
有一点区别,就是要引用互斥的概念,因为缓冲区是一个临界资源,它始终只能有一个进程对其进行操作,所以我们就可以用一个互斥信号量来完成这一点,所以当某一个进程要使用到缓冲区之前,我们就进行以下判断,判断这个缓冲区现在是不是空闲呢?是不是有生产者或者消费者的进程在使用这个这个缓冲区呢?如果有,mute的初值为1,当有人使用这个缓冲区的时候,这个mute的值就由1变为0,这时,第二个进程向再来操作这个缓冲区,就不可能了,就会被阻塞,当第一个进程使用完缓冲区
公交车司机与售票员的问题:
我们来分析这个过程,我们把S1和S2的初值都设为0。我们来分析分析:
1、P(S1):S1=S1-1=-1,那么司机进程就被暂停,等会售票员进程,售票员关车门。
2、V(S1):S1=S1+1=0,激活了司机进程,那么司机就开始启动车辆、正常行驶、到站停车,当然售票员也有可能同时在售票。
3、P(S2):S2=S2-1,售票员在售票之后的进程就被暂停,等待司机进程。这样就避免了售票员售票之后就开车门了。因为这是不允许的。
4、V(S2):S2=S2+1,司机到站停车之后,就激活了售票员P(S2)的进程,那么售票员就进程 开车门、上下客的操作。
那么这个进程就完成了。
其实这些例子都是我们生活中实实在在的例子,所以这样讲起来大家就比较容易接受。学习本来就是一个很轻松的事情。