Appearance
读者-写者问题
考情分析
读者-写者问题是 408 真题中的高频同步问题,常考读者优先方案的 PV 操作和 readcount 的互斥保护。🔥🔥🔥 高频核心。
数据库被很多人同时查询没问题,但一旦有人要修改数据,就必须独占——不能一边改一边让别人读到写了一半的脏数据。这种"读共享、写互斥"的场景,就是读者-写者问题。
问题描述
- 多个读者可以同时读取共享数据
- 写者必须独占访问——写时不能有其他读者或写者
- 读者和写者不能同时访问
| 关系 | 说明 |
|---|---|
| 读者-读者 | 不互斥(可以同时读) |
| 读者-写者 | 互斥 |
| 写者-写者 | 互斥 |
读者优先方案
semaphore rw_mutex = 1; // 读写互斥信号量
semaphore mutex = 1; // 保护 readcount 的互斥
int readcount = 0; // 当前读者数量
// 写者进程
writer() {
P(rw_mutex); // 申请写权限
写操作;
V(rw_mutex); // 释放写权限
}
// 读者进程
reader() {
P(mutex); // 保护 readcount
readcount++;
if (readcount == 1) // 第一个读者到达
P(rw_mutex); // 阻止写者
V(mutex);
读操作; // 多个读者可以同时读
P(mutex); // 保护 readcount
readcount--;
if (readcount == 0) // 最后一个读者离开
V(rw_mutex); // 允许写者
V(mutex);
}关键点分析
readcount是共享变量,需要用mutex保护- 第一个读者到达时执行
P(rw_mutex)锁住写者 - 最后一个读者离开时执行
V(rw_mutex)放行写者 - 读者在读操作期间不持有 mutex,因此多个读者可以同时读
读者优先的问题
如果不断有新读者到达,readcount 始终不为 0,写者可能永远等不到机会 → 写者饥饿。
读写公平方案
增加一个信号量 w,让写者可以「排队」:
semaphore rw_mutex = 1;
semaphore mutex = 1;
semaphore w = 1; // 新增:用于实现公平
int readcount = 0;
writer() {
P(w); // 在 w 上排队
P(rw_mutex);
写操作;
V(rw_mutex);
V(w);
}
reader() {
P(w); // 在 w 上排队
P(mutex);
readcount++;
if (readcount == 1)
P(rw_mutex);
V(mutex);
V(w); // 立即释放 w,让后续进程排队
读操作;
P(mutex);
readcount--;
if (readcount == 0)
V(rw_mutex);
V(mutex);
}这样写者到达后,后续的读者会在 P(w) 上等待,写者不会永远等待。
交互可视化
考研高频考点
- 🔥🔥🔥 读者优先方案的完整 PV 操作(必须会默写)
- 🔥🔥🔥 readcount 需要用 mutex 保护的原因
- 🔥🔥🔥 第一个读者 P(rw_mutex)、最后一个读者 V(rw_mutex) 的逻辑
- 🔥🔥 读者优先方案中写者可能饥饿
- 🔥 读写公平方案的思路
读者-写者问题是两类角色的互斥。下一篇看一个更极端的场景——哲学家进餐问题,多个进程争夺多个资源,直接引出死锁。