本文讲解计算机的 PV 操作、 PV 操作在生产消费者模型中的应用、PV 操作在前趋图中的应用。
首先了解三个基本概念,分别是临界资源、临界区和信号量。
临界资源:多个进程需要共享使用的资源,如打印机。
临界区:各个进程访问临界资源的那一段代码。
信号量:在 PV 操作中的一种变量。
PV 操作是由 P 操作和 V 操作组成的操作原语(这不废话 ),原语是不能中断的流程,可以理解为 Java 的事务,要么都执行,要么都不执行,不存在执行一半的情况。
信号量就是被 P 操作或 V 操作所操控的变量,信号量通常用 S 标识,P 操作用 P(S)标识,V 操作用 V(S) 表示。
P(S)操作(P 操作)可以将信号量 S 减一,即执行 S = S - 1。如果 S >= 0,则进程继续执行;若 S < 0,进程进入等待队列,变为等待状态。
V(S)操作(V 操作)可以将信号量 S 加一,即执行 S = S + 1。如果 S > 0,则进程继续执行;若 S <= 0,从等待队列释放一个等待进程。
PV 操作存在的意义,就是实现不同进程之间的同步和互斥,简单流程如下图所示。
还是回到之前说的生产消费模型,如下图所示。
生产消费者的运行流程如下图所示。
在公司食堂,员工排队取菜是再也正常不过的事情了。食堂阿姨在窗口放菜,员工取餐。
如果用进程 A 代表食堂阿姨放菜的工作进程,进程 B 代表员工取菜的工作进程,那么进程 A 就被看做生产者,进程 B 就被看做消费者。
没有使用 PV 操作的进程
生产者的进程 A:生产一个产品(饭菜,下同)⇒ 将产品放到缓冲区(食堂窗口,下同)。
消费者的进程 B:消费一个产品 ⇒ 从缓冲区中取出产品。
正常来说系统可以运行,但会出现两种特殊情况。
生产者生产出产品,但缓冲区不够放。
消费者尝试消费产品,但缓冲区产品为空。
这就会导致整套系统出现异常,造成不可估计的后果,所以,我们要引入 PV 操作,当缓冲区不够放时,要及时把进程阻塞起来,等待消费者消费后再放上去。
使用 PV 操作的进程
生产者的进程 A:生产一个产品 ⇒ 执行 P(S1) 操作 ⇒ 将产品放到缓冲区 ⇒ 执行 V(S2) 操作。
消费者的进程 B:消费一个产品 ⇒ 执行 P(S2) 操作 ⇒从缓冲区中取出产品 ⇒ 执行 V(S1) 操作。
其中 S1 的初始值为 1,代表缓冲区的剩余客房容量。
其中 S2 的初始值为 0,代表缓冲区剩余的产品容量。
某家书店因疫情管控,最多允许 N 位顾客进入,你可认为顾客都会进入购书结算。
将收银员和购书者看做不同的进程,并利用 PV 操作模拟进程的同步互斥,如下图所示。
设置信号量 S1 = 0、S2 = 0、SN = N,PV 流程图的操作 A、B、C、D 的结果为?
首先分析购书者的进程,信号量 Sn 代表着书店剩余可进入的购书者,当购书者进入书店,执行 P(Sn)操作,将信号量 Sn 减一。等到购书者离开书店后,执行 V(Sn)操作,将信号量 Sn 加一,这个没有问题。
重点是当购书者选好书之后,要进行付款的流程,信号量 S1 和 S2 就是用来控制收银员收款的变量。
我们设 S1 信号量代表收银员收费窗口服务的人数,初始人是空的,所以 S1 信号量为 0。
购书者申请付款,收银员开始接待,那么就需要执行 V(S1) 操作,将 S1 加一。
所以操作 A 应填写 V(S1)。
接下来分析收银员进程,收银员开始收款时,首先要开始对购书者进行服务,即服务一个【收银员收费窗口服务的人数】,即信号量 S1,需要在操作 C 的位置需要将信号量 S1 减一,将这位购书者置为己有,不让其他收银员对其服务,所以操作 C 应填写 P(S1)。
我们设 S2 信号量代表收银员收款完成的购书者人数,初始人是空的,所以 S2 信号量为 0。
付款完成后,对于收银员来说,付款流程结束,要将【收银员收款完成的购书者人数】加一,即执行 V(S2)操作,将S2 加一,所以操作 D 应填写 V(S2)。
最后对于购书者来说,付款完成后就可以正常离开书店,即【收银员收费窗口服务的人数】减一,执行 P(S2)操作,所以操作 B 应填写 P(S2)。
最终结果如下图所示。
前趋图这个无循环图的组成包括了有向边和结点。
前趋图通常用于表现进程中事务之间先后顺序的制约关系。
前趋图中的各个结点都可以表示为一条程序语句、一个程序段落或者是一个实际进程。
各个结点间的有向边,可以表示两个结点之间存在的前趋关系,即必须先执行什么,再执行什么。
PV 操作在前趋图中也有着广泛应用。
比如有这样的一个前趋图,如下图所示。
我们可以发现,必须先执行 A 和 B,在执行 C,然后再执行 D 和 E。
如何在程序中控制该套系统的正常运行,即可用 PV 操作来实现。
使用信号量 S1、S2、S3、S4 。
在执行 A 操作时,执行 V(S1)。
在执行 B 操作时,执行 V(S2)。
在执行 C 操作时,执行 P(S1)、P(S2)、V(S3)、V(S4)。
在执行 D 操作时,执行 P(S3)。
在执行 E 操作时,执行 P(S4)。
这就是 PV 操作在前趋图中的简单应用。
本文讲解了计算机的 PV 操作,还有 PV 操作在生产消费者模型中的应用,和在前趋图中的应用。