Author : Cyan_RA9
Source : 【卡码笔记】网站
Question : 解释一下PV操作,以及它在进程同步中的应用?
【简要回答】
- PV操作与信号量机制的关系:
- P操作和V操作是信号量的两种原子操作,通过增减信号量值实现资源分配与释放,信号量(Semaphore)是一种同步工具,通过PV操作(原子增减操作)协调多进程/线程对共享资源的访问。
- PV操作的原理:
- P操作(wait原语 / 等待):申请资源,若资源不足则阻塞当前进程。
- V操作(signal原语 / 释放):释放资源,若有等待进程则唤醒。
- PV操作在进程同步中的应用
- 互斥访问(Mutual Exclusion):通过二进制信号量保护临界区。
- 同步协作(Synchronization and Coordination):通过计数信号量协调进程执行顺序。
- 经典问题(Classic Scenarios):生产者 - 消费者 问题;哲学家进餐 问题;读者 - 写者 问题。
【详细回答】
PV操作与信号量机制的关系
- PV操作的角色:
- P操作和V操作是信号量的两种原子操作,通过增减信号量值实现资源分配与释放。
- 信号量机制:
- 定义:信号量(Semaphore)是一种同步工具,通过PV操作(原子增减操作)协调多进程/线程对共享资源的访问。在操作系统中,信号量是一种关联一类临界资源的数据结构,信号量的不同值表示一个临界资源的不同状态。
- 分类:
- 从用途和取值范围出发,可分为二进制信号量 和 计数信号量。
- 二进制信号量(互斥信号量):值为0或1,用于互斥访问(如临界区保护)。
- 计数信号量(同步信号量):值可正可负,具体取决于其实现机制,用于管理多个同类资源(如缓冲区空槽);当同步信号量的值大于等于0时,信号量的绝对值表示可用资源的数量;当同步信号量的值小于0时,信号量的值的绝对值就是等待该资源的进程数。
- 从实现机制和行为特性出发,可分为整型信号量 和 记录型信号量。
- 整型信号量:把信号量定义为一个用于表示资源数目的整数S,对于S的访问(加减)只能通过原语实现;可以把整型信号量机制看作是对S定义了三种操作——①初始化;②减1;③加1。整型信号量只能取 非负整数。
- 记录型信号量:在整型信号量中,如果S ≤ 0时,P操作会陷入“忙等”状态,不满足同步机制设计准则的“让权等待”准则。记录型信号量在 整型信号量 的基础上,增加了一个被阻塞进程的队列,用于链接所有等待相应资源的进程,以实现“让权等待”。记录型信号量可正可负。
- 从用途和取值范围出发,可分为二进制信号量 和 计数信号量。
PV操作的原理
- P操作(wait原语 / 等待):
- P原语,又称wait原语,用于实现对S值的减1,减1相当于申请并获取一个资源,如果资源不足则开始等待,所以P操作可能 阻塞 进程。
- V操作(signal原语 / 释放):
- V原语,又称signal原语,用于实现对S值的加1,加1相当于使用结束并释放一个资源,如果有进程在等待该资源,则唤醒一个进程,所以V操作可能唤醒进程。
PV操作在进程同步中的应用
- 互斥访问(Mutual Exclusion):
- 场景:多个进程需互斥访问共享资源(如打印机、共享内存)。
- 实现:初始化二进制信号量 mutex = 1;每个进程在访问临界区前需对互斥量mutex执行P操作,在退出临界区后需对互斥量mutex执行V操作。
- 同步协作(Synchronization and Coordination):
- 场景:多个进程在执行中有确定的前后关系,例如进程Pa用于拉取数据,进程Pb用于对数据进行处理,那么Pb就必须在Pa之后执行。
- 实现:可以将同步信号量的初始值置为0,只要进程Pa没有对资源执行V操作,那么进程Pb就会始终在P操作中阻塞等待;只有当进程Pa先执行了V操作,进程Pb才能成功执行P操作,继而去处理数据。
- 经典问题(Classic Scenarios):
- 生产者 - 消费者问题:是对合作进程中内部关系的抽象化,可以描述为一组生产者和一群消费者一起工作,通过一个大小为 n 的有限缓冲区进行生产和消费。一个缓冲区可以容纳 n 个产品,其中生产者负责投放产品,消费者负责消费产品。
- 哲学家进餐问题:是进程同步的一个典型问题,可以描述为有五个哲学家围坐在一起,每两个人中间只有一只筷子,每根筷子都不相同,只有当一个哲学家既拿起他左边的筷子又拿起他右边的筷子时,才能吃饭。如果五个哲学家同时拿起他们左边的筷子,就会出现循环等待的情况,导致死锁发生。
- 读者 - 写者问题:是对数据对象(数据文件或记录)的访问模型,可以描述为有一个共享文件File,允许几个读者进程同时读取File中的内容,但在任何时刻只允许一个写者进程写入或修改File中的内容。当一个进程正在读取File中的内容时,允许其他进程也读取File但不允许其他进程写入或修改File;当一个进程正在对File进行写入或修改时,既不允许其他进程读取File也不允许其他进程写入或修改File。
【知识拓展】
- 一张“读者 - 写者问题”的示意图如下所示:
- 生产者 - 消费者问题的解决方案:
- 同步准则:
① 如果缓冲区已满,生产者试图放入产品时应当被阻塞,等待消费者取出产品、缓冲区有空位后再将其唤醒。
② 如果缓冲区为空,消费者试图拿取产品时应当被阻塞,等待生产者放入产品、缓冲区有资源后再将其唤醒。 - 参考实现:
① 设置两个同步信号量:empty表示当前缓冲区中 空位 的数量,初始值为n,对应缓冲区大小为n;full表示当前缓冲区中已放入资源的数量(即 非空位 的数量),初始值为0。
② 设置一个互斥信号量:mutex = 1,实现临界区的互斥访问。
- 同步准则:
- 哲学家进餐问题的解决方案:
- 最对允许四名哲学家同时进餐(破坏了死锁四个必要条件中的“循环等待”条件)。
- 只有在哲学家的左右两边都有筷子的情况下,才允许哲学家进餐(破坏了死锁四个必要条件中的“请求和保持”条件)。
- 让编号为奇数的哲学家先拿左手边的筷子,再拿右手边的筷子,编号为偶数的哲学家的拿取顺序与之相反(破坏了“循环等待”条件)。
- 读者 - 写者问题的解决方案:
- 读者优先:读进程具有优先权,其访问临界区时,只要有一个读进程在读,读进程就能继续获得对临界区的控制权,但可能导致写进程饥饿。
- 写者优先:写进程具有优先权,如果有写进程希望访问临界区,就会禁止新的读进程进入临界区,解决了写进程饥饿的问题。
- 读写公平:不偏袒读者进程或写者进程中的任何一方,仅根据读写请求的到达顺序来赋予读写的权利。