当前位置: 首页 > news >正文

PV操作详解:进程同步核心机制

PV操作是一种用于实现进程间同步与互斥的核心机制由荷兰计算机科学家E.W.Dijkstra提出。它包含两个不可中断的原子操作通常与信号量Semaphore结合使用。1. PV操作与信号量信号量是一个用于控制多个进程对共享资源访问的整型变量。其值通常代表可用资源的数量。根据信号量的用途其初始化值有所不同。PV操作的定义如下P操作(Proberen, 意为“尝试”或“等待”): 当一个进程需要申请一个资源时执行P操作。它会检查信号量的值如果值大于0则将其减1表示成功获取一个资源如果值等于0则进程被阻塞进入等待队列直到有资源被释放。V操作(Verhogen, 意为“增加”或“释放”): 当一个进程释放一个资源时执行V操作。它会将信号量的值加1。如果此时有进程正在等待该资源即等待队列非空则会唤醒其中一个等待进程。信号量可分为互斥信号量 (Mutex): 用于实现互斥访问其初始值通常为1保证同一时刻只有一个进程能进入临界区。资源信号量: 用于实现同步其初始值代表某类资源的初始可用数量例如生产者-消费者问题中的缓冲区空位数量empty或已存放产品数量full。2. PV操作的应用模型PV操作是解决一系列经典并发问题的基石。2.1 生产者-消费者问题这是最经典的同步问题。生产者进程生产数据放入缓冲区消费者进程从缓冲区取出数据消费。需要解决三个同步互斥点1缓冲区满时生产者等待2缓冲区空时消费者等待3缓冲区的访问必须是互斥的。假设缓冲区大小为N使用三个信号量mutex: 互斥信号量初始为1用于保证对缓冲区的互斥访问。empty: 资源信号量初始为N代表空缓冲区数量。full: 资源信号量初始为0代表已填充的缓冲区数量。其伪代码实现如下// 生产者进程 void producer() { while (true) { 生产一个产品 item; P(empty); // 申请一个空缓冲区若无则等待 P(mutex); // 申请进入临界区访问缓冲区 将 item 放入缓冲区; V(mutex); // 离开临界区释放缓冲区访问权 V(full); // 释放一个“已填充”资源通知消费者 } } // 消费者进程 void consumer() { while (true) { P(full); // 申请一个已填充的产品若无则等待 P(mutex); // 申请进入临界区访问缓冲区 从缓冲区取出一个产品 item; V(mutex); // 离开临界区释放缓冲区访问权 V(empty); // 释放一个“空位”资源通知生产者 消费 item; } }注意两个P操作的顺序至关重要。生产者必须先P(empty)再P(mutex)消费者必须先P(full)再P(mutex)。如果顺序颠倒可能导致死锁。例如若生产者先P(mutex)获得了缓冲区锁但发现empty0缓冲区满而阻塞此时消费者因无法获得mutex而无法消费释放空位双方将永远等待下去。2.2 读者-写者问题该问题中多个读者进程可以同时读取共享数据但写者进程必须独占访问。它更侧重于实现复杂的同步策略例如“写者优先”或“读者优先”。一个简单的“读者优先”模型可能导致写者饥饿可以使用一个互斥信号量rw_mutex控制写互斥初始为1和一个计数器read_count记录当前读者数量及其保护锁mutex初始为1来实现。// 写者进程 void writer() { while (true) { P(rw_mutex); // 申请独占写权限 执行写操作; V(rw_mutex); // 释放写权限 } } // 读者进程 void reader() { while (true) { P(mutex); // 保护 read_count read_count; if (read_count 1) { P(rw_mutex); // 第一个读者需要“锁住”写者 } V(mutex); 执行读操作; P(mutex); read_count--; if (read_count 0) { V(rw_mutex); // 最后一个读者“释放”写者 } V(mutex); } }3. 使用PV操作实现进程互斥对于只需要互斥访问的临界区使用一个初始值为1的互斥信号量即可。semaphore mutex 1; // 互斥信号量 void process_i() { while (true) { // ... 剩余区 P(mutex); // 进入区尝试获取锁 // ... 临界区访问共享资源 V(mutex); // 退出区释放锁 // ... 剩余区 } }4. 信号量的底层实现与注意事项PV操作必须是原子操作即在执行期间不可被中断。在单处理器系统中可以通过屏蔽中断来实现在多处理器系统中则需要借助硬件提供的特殊原子指令如Test-and-Set, Compare-and-Swap。信号量的实现通常包含一个整型值value和一个进程等待队列queue。P操作和V操作的具体逻辑如下表所示操作伪代码逻辑描述P(semaphore S)S.value--;if (S.value 0) {将当前进程状态置为“等待”将当前进程PCB插入S.queue调度其他进程运行}V(semaphore S)S.value;if (S.value 0) {从S.queue中移出一个等待进程P将进程P状态置为“就绪”将P插入就绪队列}核心要点当S.value为负数时其绝对值表示正在等待该信号量的进程数量。在使用PV操作时必须警惕死锁。死锁发生的四个必要条件是互斥、持有并等待、非抢占、循环等待。错误的P操作顺序如前文生产者-消费者问题所述或资源分配不当都可能引发死锁。银行家算法是一种经典的死锁避免算法它通过预判分配后系统是否处于安全状态来决定是否分配资源。参考来源pv原语模拟实现_手把手教你如何玩转操作系统信号量和PV操作PV操作【操作系统学习笔记二】之 进程进程调度进程同步与互斥计算机四级嵌入式之操作系统原理四并发与同步信号量Semaphore(信号量)
http://www.gsyq.cn/news/1294565.html

相关文章:

  • AI生成20万字专著不再难!专业AI写专著工具为你保驾护航!
  • 数字示波器原理与工程应用全解析
  • 在arm7开发板上观测Taotoken API调用的延迟与稳定性表现
  • LaTeX变量定义避坑指南:为什么你的\M后面空格消失了?
  • HC-SR501人体红外感应模块:从原理到实战的智能感知设计
  • 企业级应用如何利用Taotoken管理多个AI模型API密钥与用量
  • Pattern Recognition投稿实战:从LaTeX排版到录用见刊的全流程复盘
  • 工业智能化四大趋势:边缘AI、实时控制、无线连接与能效管理实战解析
  • Divinity Mod Manager:如何用技术架构解决《神界:原罪2》模组管理的复杂性?
  • 告别时序烦恼:用Xilinx SelectIO IP核搞定AD9747 DAC驱动(附完整Vivado配置流程)
  • 如何用CELLxGENE让单细胞数据分析像刷抖音一样简单?
  • GHelper终极指南:3步解决华硕笔记本性能控制难题
  • ChatGPT API代理层实战:简化集成、优化成本与提升稳定性
  • ARM开发板与SoM模块技术解析及应用实践
  • iOS 17-26越狱终极指南:5个安全解锁iPhone隐藏功能的专业方法
  • 别再手动调参了!用Simulink系统辨识工具箱,5分钟搞定Buck电路的PID控制器设计
  • Cortex-M0非对齐访问陷阱:从硬件错误中断到__attribute__((aligned))的实战避坑指南
  • 数电公式化简别再死记硬背了!5个实用口诀搞定‘与或非’表达式
  • 从硬件原理图到Ping通:我的STM32F407 RMII以太网调试全记录(含H1102NL变压器替换思考)
  • 别再只调卷积核了!用PyWavelets+DCT给你的图像增强模型加个‘细节放大镜’
  • 555时基电路深度解析:从核心原理到三大工作模式实战
  • 别再手动改防火墙了!用这条组策略,一键修复AD域强制更新时的RPC报错
  • 不只是跑通:用D435i和VINS-Mono做个室内小车的视觉里程计demo
  • G-Helper终极指南:华硕笔记本轻量级控制中心完整解析与实战应用
  • 保姆级教程:用Debootstrap和QEMU在Ubuntu 22.04上制作ARM64 Debian 12 rootfs
  • 【ElevenLabs泰卢固文语音实战指南】:2024年唯一经实测验证的本地化语音合成落地方案
  • Xenos:Windows平台终极DLL注入工具完全指南
  • 你还在手动调参?——用Python自动化脚本批量生成表现主义变体并智能评分(GitHub开源已验证)
  • 如何用G-Helper快速优化华硕笔记本性能:5分钟实现硬件精准控制终极指南
  • 基于SpringBoot的物业缴费报修系统毕设