### 如何用PV原语实现进程间的互斥与同步 #### PV原语概念与作用 在计算机科学领域,特别是操作系统理论中,PV操作是用于控制并发进程之间互斥与同步的关键机制之一。PV操作(也称作信号量操作)是由荷兰科学家Edsger W. Dijkstra提出的一种原子性操作,主要包括两种类型:P操作(尝试获得资源)和V操作(释放已占用资源)。这些操作确保了资源的安全访问,并有效地管理了进程之间的同步问题。 #### 信号量与PV原语 信号量是一种用于同步进程的数据结构,它可以是一个简单的整数值。当信号量值为正时,表示系统中有可用的共享资源;当信号量值为负时,则表示有进程正在等待获取资源。PV操作就是通过修改这个信号量来达到进程间同步的目的。 1. **P操作**: - 将信号量减一。 - 如果信号量仍为正数或零,则进程继续执行。 - 如果信号量变为负数,则将该进程挂起,并将其添加到信号量对应的等待队列中。 2. **V操作**: - 将信号量加一。 - 如果信号量为正数或零,则进程继续执行。 - 如果信号量仍为负数,则唤醒等待队列中的一个进程,并让其重新参与调度。 #### 应用实例分析 为了更深入地理解PV原语的工作原理及其在实际应用中的作用,下面将通过几个具体的案例来探讨PV原语是如何帮助实现进程间的互斥与同步的。 ##### 例1:两个进程共享一个资源 假设存在两个进程A和B,它们需要共享同一个资源,比如一台打印机。为了避免冲突,我们需要确保一次只有一个进程可以使用该资源。因此,可以通过设置一个信号量`s`来控制对打印机的访问: ```plaintext begin s: semaphore; s := 1; cobegin process A begin L1: P(s); // 使用打印机 V(s); goto L1; end; process B begin L2: P(s); // 使用打印机 V(s); goto L2; end; coend; end; ``` 在这个例子中,信号量`s`的初始值为1,表示资源是可用的。每当有一个进程想要使用打印机时,它会执行P操作,这将使信号量减一。如果此时信号量仍为正数或零,则进程可以继续并使用打印机;如果信号量变为负数,则该进程被挂起直到另一个进程执行V操作释放资源。这种方式保证了任何时刻只有一个进程能够访问打印机,从而实现了互斥。 ##### 例2:银行中多个柜员服务多个客户 考虑银行中存在多个柜员和多个客户的情况。每个柜员在服务一个客户之后需要释放该客户,以便其他柜员可以继续服务其他客户。为了确保服务过程中的同步性,我们可以使用信号量来控制: ```plaintext begin s: semaphore; s := 20; // 假设共有20个柜员 cobegin process PI (I = 1, 2, ...) begin P(s); // 服务客户 // ... V(s); end; coend ``` 在这个场景中,信号量`s`的初始值为20,代表可用的柜员数量。每当有一个柜员开始服务客户时,执行P操作,这将使信号量减一;当服务完成后,执行V操作,使得信号量加一,释放资源。这种方式保证了柜员资源的有效管理和利用。 ##### 例3:交通灯控制 再来看一个更为复杂的案例,即交通灯控制系统。在这个系统中,红绿灯交替控制着车辆的通行。我们可以通过设置两个信号量`s1`和`s2`来分别控制红灯和绿灯的状态: ```plaintext begin s1, s2: semaphore; s1 := 1; // 绿灯信号量 s2 := 0; // 红灯信号量 cobegin process A (绿灯) begin L1: P(s1); // 开启绿灯 V(s2); goto L1; end; process B (红灯) begin L2: P(s2); // 开启红灯 V(s1); goto L2; end; coend; end; ``` 这里,信号量`s1`控制绿灯,初始值为1;信号量`s2`控制红灯,初始值为0。通过P操作和V操作的配合使用,实现了交通灯的自动切换,确保了交通的有序进行。 ##### 例4:火车驾驶员与售票员的协作 考虑火车驾驶员与售票员之间的协作。火车驾驶员需要等待售票员完成售票才能出发,而售票员需要知道驾驶员是否已经准备就绪。这种情况下,可以设置两个信号量`run`和`stop`来协调双方的操作: ```plaintext begin stop, run: semaphore stop := 0; // 表示驾驶员尚未准备好 run := 0; // 表示售票员尚未完成售票 cobegin driver: begin L1: P(run); // 等待售票员完成售票 // 准备出发 V(stop); // 告诉售票员已经准备好 goto L1; end; conductor: begin L2: // 完成售票 V(run); // 告诉驾驶员可以出发 // 等待驾驶员准备好 P(stop); // 出发 goto L2; end; coend; end; ``` 在这个案例中,信号量`run`用于协调售票员的操作,信号量`stop`用于协调驾驶员的操作。通过这两种信号量的配合使用,确保了火车驾驶员与售票员之间顺畅的协作,实现了系统的正常运行。 ### 总结 PV原语及其相关的信号量机制是实现进程间互斥与同步的重要工具。通过合理设置信号量的初值以及正确使用P操作和V操作,可以有效地解决并发进程之间的资源竞争问题,保证了系统的稳定性和可靠性。无论是简单资源的访问控制,还是复杂系统中的多进程协作,PV原语都能提供强大的支持,是现代操作系统中不可或缺的一部分。
P操作和V操作是不可中断的程序段,称为原语。PV原语及信号量的概念都是由荷兰科学家E.W.Dijkstra提出的。信号量sem是一整数,sem大于等于零时代表可供并发进程使用的资源实体数,但sem小于零时则表示正在等待使用临界区的进程数。
P原语操作的动作是:
(1) sem减1;
(2) 若sem减1后仍大于或等于零,则进程继续执行;
(3) 若sem减1后小于零,则该进程被阻塞后进入与该信号相对应的队列中,然后转进程调度。
V原语操作的动作是:
(1) sem加1;
(2) 若相加结果大于零,则进程继续执行;
(3) 若相加结果小于或等于零,则从该信号的等待队列中唤醒一等待进程,然后再返回原进程继续执行或转进程调度。
PV操作对于每一个进程来说,都只能进行一次,而且必须成对使用。在PV原语执行期间不允许有中断的发生。
用PV原语实现进程的互斥
由于用于互斥的信号量sem与所有的并发进程有关,所以称之为公有信号量。公有信号量的值反映了公有资源的数量。只要把临界区置于P(sem) 和V(sem)之间,即可实现进程间的互斥。就象火车中的每节车厢只有一个卫生间,该车厢的所有旅客共享这个公有资源:卫生间,所以旅客间必须互斥进入卫生间,只要把卫生间放在P(sem) 和V(sem)之间,就可以到达互斥的效果。以下例子说明进程的互斥实现。
例1 生产围棋的工人不小心把相等数量的黑子和白子混装载一个箱子里,现要用自动分拣系统把黑子和白子分开,该系统由两个并发执行的进程组成,功能如下:
(1) 进程A专门拣黑子,进程B专门拣白子;
(2) 每个进程每次只拣一个子,当一个进程在拣子时不允许另一个进程去拣子;
分析:第一步:确定进程间的关系。由功能(2)可知进程之间是互斥的关系。第二步:
确定信号量及其值。由于进程A和进程B要互斥进入箱子去拣棋子,箱子是两个进程的公有资源,所以设置一个信号量s,其值取决于公有资源的数目,由于箱子只有一个,s的初值就设为1。
实现:begin
s:semaphore;
s:=1;
cobegin
process A
begin
L1: P(s);
拣黑子;
V(s);
- 上课小蜗牛2014-03-26很全面的介绍,值得学习。对操作系统的进程管理学习很有帮助!
- 粉丝: 1
- 资源: 10
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助