Update 计算机操作系统 - 进程管理 - 进阶.md

补充读者-写者问题三种实现的时序对比配图,更新写优先与公平排队代码的中文注释与格式。
This commit is contained in:
CyC2018
2026-10-30 20:19:32 +08:00
parent faa33c34da
commit 6decf1c709
2 changed files with 60 additions and 77 deletions
Binary file not shown.

After

Width:  |  Height:  |  Size: 208 KiB

@@ -13,56 +13,56 @@
主线见[计算机操作系统 - 进程管理 · 读者-写者问题](计算机操作系统%20-%20进程管理.md#2-读者-写者问题),那里用 count、count_mutex 和 data_mutex 实现的是读者优先:只要还有读者在读,后到的读者可以直接进入,写者要一直等待。
三种实现的差别可以用同一组到达顺序来比较(按主线和本节的代码逐行模拟,信号量按先进先出的顺序唤醒):
<div align="center"> <img src="pics/rw-priority-timeline.png" width="760px"/> </div><br>
以下内容由 [@Bandi Yugandhar](https://github.com/yugandharbandi) 提供。
主线中的实现可能导致写者饥饿。下面的实现是写者优先的:写者进入队列之后,只需要等待在它之前进入的读者,不会被之后到达的读者一直阻塞。
```c
int readcount, writecount; //(initial value = 0)
semaphore rmutex, wmutex, readLock, resource; //(initial value = 1)
int readcount, writecount; // 初值都为 0
semaphore rmutex, wmutex, readLock, resource; // 初值都为 1
//READER
void reader() {
<ENTRY Section>
down(&readLock); // reader is trying to enter
down(&rmutex); // lock to increase readcount
readcount++;
if (readcount == 1)
down(&resource); //if you are the first reader then lock the resource
up(&rmutex); //release for other readers
up(&readLock); //Done with trying to access the resource
// 进入
down(&readLock); // 有写者在排队时,读者在这里被挡住
down(&rmutex); // 保护 readcount
readcount++;
if (readcount == 1)
down(&resource); // 第一个读者锁住资源,防止写者进入
up(&rmutex);
up(&readLock);
<CRITICAL Section>
//reading is performed
// 读
<EXIT Section>
down(&rmutex); //reserve exit section - avoids race condition with readers
readcount--; //indicate you're leaving
if (readcount == 0) //checks if you are last reader leaving
up(&resource); //if last, you must release the locked resource
up(&rmutex); //release exit section for other readers
// 退出
down(&rmutex);
readcount--;
if (readcount == 0)
up(&resource); // 最后一个读者释放资源
up(&rmutex);
}
//WRITER
void writer() {
<ENTRY Section>
down(&wmutex); //reserve entry section for writers - avoids race conditions
writecount++; //report yourself as a writer entering
if (writecount == 1) //checks if you're first writer
down(&readLock); //if you're first, then you must lock the readers out. Prevent them from trying to enter CS
up(&wmutex); //release entry section
// 进入
down(&wmutex); // 保护 writecount
writecount++;
if (writecount == 1)
down(&readLock); // 第一个写者挡住之后到达的读者
up(&wmutex);
<CRITICAL Section>
down(&resource); //reserve the resource for yourself - prevents other writers from simultaneously editing the shared resource
//writing is performed
up(&resource); //release file
down(&resource); // 写者之间互斥,并等待正在读的读者退出
// 写
up(&resource);
<EXIT Section>
down(&wmutex); //reserve exit section
writecount--; //indicate you're leaving
if (writecount == 0) //checks if you're the last writer
up(&readLock); //if you're last writer, you must unlock the readers. Allows them to try enter CS for reading
up(&wmutex); //release exit section
// 退出
down(&wmutex);
writecount--;
if (writecount == 0)
up(&readLock); // 最后一个写者放行读者
up(&wmutex);
}
```
@@ -71,55 +71,38 @@ void writer() {
以上两种实现总有一方可能饥饿。下面的实现使用一个先进先出的 serviceQueue 让读者和写者按到达顺序排队,获取共享数据的锁总能在有限时间内完成,因此不会出现饥饿。
```c
int readCount; // init to 0; number of readers currently accessing resource
int readCount; // 正在读的读者数,初值为 0
semaphore resourceAccess; // 控制对资源的读写,初值为 1
semaphore readCountAccess; // 保护 readCount,初值为 1
semaphore serviceQueue; // 按到达顺序排队,初值为 1,要求按先进先出的顺序唤醒
// all semaphores initialised to 1
Semaphore resourceAccess; // controls access (read/write) to the resource
Semaphore readCountAccess; // for syncing changes to shared variable readCount
Semaphore serviceQueue; // FAIRNESS: preserves ordering of requests (signaling must be FIFO)
void writer() {
down(&serviceQueue); // 排队
down(&resourceAccess); // 等待独占资源
up(&serviceQueue); // 轮到下一个
void writer()
{
down(&serviceQueue); // wait in line to be serviced
// <ENTER>
down(&resourceAccess); // request exclusive access to resource
// </ENTER>
up(&serviceQueue); // let next in line be serviced
writeResource(); // 写
// <WRITE>
writeResource(); // writing is performed
// </WRITE>
// <EXIT>
up(&resourceAccess); // release resource access for next reader/writer
// </EXIT>
up(&resourceAccess);
}
void reader()
{
down(&serviceQueue); // wait in line to be serviced
down(&readCountAccess); // request exclusive access to readCount
// <ENTER>
if (readCount == 0) // if there are no readers already reading:
down(&resourceAccess); // request resource access for readers (writers blocked)
readCount++; // update count of active readers
// </ENTER>
up(&serviceQueue); // let next in line be serviced
up(&readCountAccess); // release access to readCount
void reader() {
down(&serviceQueue); // 排队
down(&readCountAccess);
if (readCount == 0)
down(&resourceAccess); // 第一个读者锁住资源,写者被挡住
readCount++;
up(&serviceQueue); // 轮到下一个
up(&readCountAccess);
// <READ>
readResource(); // reading is performed
// </READ>
readResource(); // 读
down(&readCountAccess); // request exclusive access to readCount
// <EXIT>
readCount--; // update count of active readers
if (readCount == 0) // if there are no readers left:
up(&resourceAccess); // release resource access for all
// </EXIT>
up(&readCountAccess); // release access to readCount
down(&readCountAccess);
readCount--;
if (readCount == 0)
up(&resourceAccess); // 最后一个读者释放资源
up(&readCountAccess);
}
```
## 参考资料