【操作系统】经典同步问题:读者-写者 / 哲学家进餐

发布时间:2026/6/29 17:08:45

【操作系统】经典同步问题:读者-写者 / 哲学家进餐 考点频率读者-写者 ★★★★☆常考哲学家进餐 ★★★☆☆偶尔出现以概念为主难度⭐⭐⭐⭐建议重点掌握读者-写者的“读优先”模型哲学家进餐以理解死锁原因为主一、读者-写者问题Readers-Writers Problem1️⃣ 问题描述共享一个数据区如数据库多个进程并发访问读者Reader只读取数据不修改写者Writer修改数据核心约束允许多个读者同时读取读读不互斥写者与任何进程互斥读写互斥、写写互斥读者正在读时写者不能写写者正在写时读者和其他写者都不能访问这个模型在数据库、文件系统等多读少写的场景中非常典型用来平衡并发性能和数据一致性。2️⃣ 信号量设计信号量初值作用rw_mutex1读写互斥信号量用于写者和第一个/最后一个读者之间的互斥count_mutex1保护readcount的互斥信号量readcount0整数变量记录当前正在读的读者数量3️⃣ 代码实现读优先semaphore rw_mutex1;// 写者与第一个/最后一个读者的互斥semaphore count_mutex1;// 保护 readcount 的互斥intreadcount0;// 当前读者数量// 写者进程Writer(){while(true){P(rw_mutex);// 申请写权限// 执行写操作写入数据V(rw_mutex);// 释放写权限}}// 读者进程Reader(){while(true){P(count_mutex);// 保护 readcount 的访问readcount;if(readcount1){P(rw_mutex);// 第一个读者阻止写者}V(count_mutex);// 执行读操作读取数据P(count_mutex);readcount--;if(readcount0){V(rw_mutex);// 最后一个读者允许写者}V(count_mutex);}}4️⃣ 核心逻辑解析为什么只有第一个读者需要 P(rw_mutex)如果已经有读者在读后续读者不需要再申请rw_mutex它们直接进来即可——这是“读读不互斥”的体现。rw_mutex的 P 操作只执行一次第一个读者进入时V 操作也只执行一次最后一个读者离开时。为什么最后一个读者才 V(rw_mutex)只要还有读者在读写者就不能进来。所以需要等到最后一个读者离开时才释放锁。为什么 count_mutex 不可省readcount是多个读者进程共享的变量多个读者同时修改它会导致计数错误必须用互斥信号量保护。5️⃣ 读者-写者 vs 生产者-消费者对比项读者-写者生产者-消费者核心关系读者之间不互斥写者独占生产者和消费者都需要互斥计数对象读者数量缓冲区的空位/满位读者/写者优先级读优先上面方案无优先级差异修改数据写者修改读者不修改生产者和消费者都修改缓冲区6️⃣ 经典例题例题1在读者-写者问题中若readcount的当前值为3rw_mutex的值为0则以下判断正确的是 。A. 有1个写者在写数据B. 有3个读者在读数据没有写者C. 有3个读者在读数据有1个写者在等待D. 有3个读者在读数据且有1个写者正在写数据解析readcount3表示有3个读者在读rw_mutex0表示 rw_mutex 被占用。但注意rw_mutex 是由第一个读者占用的不是由写者。只要还有读者在读rw_mutex 就为0。此时写者如果请求写入会被阻塞在P(rw_mutex)上。所以当前状态是3个读者在读写者在等待如果有的话。但选项中C表述的是“有3个读者在读数据没有写者”也不一定错因为题干没有说写者存在。根据信号量值无法判断“是否有写者等待”只能判断“如果有写者它正在等待”。软考中这道题的标准答案通常在C和D之间需要看具体题干如何描述写者是否存在。记忆要点rw_mutex的值和readcount共同反映了读写状态。二、哲学家进餐问题Dining Philosophers Problem1️⃣ 问题描述5个哲学家围坐在圆桌旁桌上5根筷子每个哲学家左右各有一根。哲学家的行为思考不需要资源饥饿需要拿起左右两根筷子才能进餐进餐占用两根筷子吃完后放下核心约束每个哲学家必须拿到两根筷子才能吃饭筷子是临界资源一次只能被一个人使用必须避免死锁所有人同时拿起左边的筷子等待右边的筷子2️⃣ 信号量设计信号量初值作用chopstick[0..4]全为1每根筷子的互斥信号量3️⃣ 最简单的实现存在死锁风险semaphore chopstick[5]{1,1,1,1,1};Philosopher(i){// i 0, 1, 2, 3, 4while(true){// 思考P(chopstick[i]);// 拿起左边的筷子P(chopstick[(i1)%5]);// 拿起右边的筷子// 进餐V(chopstick[i]);// 放下左边的筷子V(chopstick[(i1)%5]);// 放下右边的筷子}}死锁场景5个哲学家同时执行P(chopstick[i])每个人都拿起了左边的筷子此时所有筷子都被占用每个人都等待右边的筷子 → 死锁。4️⃣ 死锁的解决方案方案思路说明方案一限制并发数最多允许4个人同时拿筷子至少保证1人能拿到两根筷子方案二奇偶编号法奇数哲学家先拿左后拿右偶数先拿右后拿左破坏循环等待方案三两阶段申请先同时申请两根筷子拿不到则全部释放类似于“原子申请”5️⃣ 方案一代码限流4人semaphore chopstick[5]{1,1,1,1,1};semaphore max_diners4;// 最多4人同时进餐Philosopher(i){while(true){// 思考P(max_diners);// 限制并发数P(chopstick[i]);P(chopstick[(i1)%5]);// 进餐V(chopstick[i]);V(chopstick[(i1)%5]);V(max_diners);// 释放名额}}6️⃣ 经典例题例题1在哲学家进餐问题中若所有哲学家同时拿起左边的筷子则系统发生了 。A. 饥饿B. 死锁C. 互斥D. 同步解析所有人同时拿起左边筷子都在等待右边筷子形成循环等待→死锁。选B。例题2以下哪种方法不能解决哲学家进餐的死锁问题 。A. 限制同时进餐的人数B. 规定奇偶编号的哲学家拿筷子的顺序不同C. 增加筷子的数量D. 要求哲学家一次申请所有需要的筷子解析C不是根本解决方案增加筷子只是改变了资源数量但无法从逻辑上破坏死锁的四个条件。选C。三、三种经典同步问题对比对比项生产者-消费者读者-写者哲学家进餐核心关系生产与消费的速率匹配读读共享、读写互斥资源竞争与死锁信号量数量3个empty, full, mutex2个rw_mutex, count_mutex 计数变量5个每根筷子一个主要难点P操作的顺序第一个/最后一个读者的特殊处理避免死锁考试频率最高较高中等四、记忆口诀读者写者读优先计数变量是关键。首读申请写者锁末读释放才安全。哲学家吃饭难五根筷子五人抢。限流换序或全拿死锁预防记心间。五、小测验评论区对答案在读者-写者问题中若采用“读优先”策略当读者正在读数据时写者到达。以下说法正确的是 。A. 写者可以立即写数据B. 写者必须等待所有读者离开后才能写C. 写者可以打断读者优先写数据D. 读者和写者可以同时访问数据本专栏日更2篇点击头像 → 专栏《软考中级高频考点》订阅第一时间接收新内容#软考中级 #软件设计师 #读者写者 #哲学家进餐 #PV操作 #操作系统

相关新闻