mirror of
https://github.com/CyC2018/Interview-Notebook.git
synced 2026-10-30 07:33:45 +00:00
Update 计算机操作系统 - 进程管理 - 进阶.md
新增进阶篇,收录读者-写者问题的写者优先与公平实现。
This commit is contained in:
@@ -0,0 +1,128 @@
|
||||
# 计算机操作系统 - 进程管理 - 进阶
|
||||
<!-- GFM-TOC -->
|
||||
* [计算机操作系统 - 进程管理 - 进阶](#计算机操作系统---进程管理---进阶)
|
||||
* [经典同步问题](#经典同步问题)
|
||||
* [读者-写者问题](#读者-写者问题)
|
||||
* [参考资料](#参考资料)
|
||||
<!-- GFM-TOC -->
|
||||
|
||||
|
||||
## 经典同步问题
|
||||
|
||||
### 读者-写者问题
|
||||
|
||||
主线见[计算机操作系统 - 进程管理 · 读者-写者问题](计算机操作系统%20-%20进程管理.md#2-读者-写者问题),那里用 count、count_mutex 和 data_mutex 实现的是读者优先:只要还有读者在读,后到的读者可以直接进入,写者要一直等待。
|
||||
|
||||
以下内容由 [@Bandi Yugandhar](https://github.com/yugandharbandi) 提供。
|
||||
|
||||
主线中的实现可能导致写者饥饿。下面的实现是写者优先的:写者进入队列之后,只需要等待在它之前进入的读者,不会被之后到达的读者一直阻塞。
|
||||
|
||||
```c
|
||||
int readcount, writecount; //(initial value = 0)
|
||||
semaphore rmutex, wmutex, readLock, resource; //(initial value = 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
|
||||
|
||||
<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
|
||||
}
|
||||
|
||||
//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
|
||||
|
||||
<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
|
||||
|
||||
<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
|
||||
}
|
||||
```
|
||||
|
||||
每个读者都必须先获取 readLock,而只有第一个写者需要获取 readLock,并且直到队列中没有写者时才会释放,因此这种实现可能导致读者饥饿。
|
||||
|
||||
以上两种实现总有一方可能饥饿。下面的实现使用一个先进先出的 serviceQueue 让读者和写者按到达顺序排队,获取共享数据的锁总能在有限时间内完成,因此不会出现饥饿。
|
||||
|
||||
```c
|
||||
int readCount; // init to 0; number of readers currently accessing resource
|
||||
|
||||
// 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); // wait in line to be serviced
|
||||
// <ENTER>
|
||||
down(&resourceAccess); // request exclusive access to resource
|
||||
// </ENTER>
|
||||
up(&serviceQueue); // let next in line be serviced
|
||||
|
||||
// <WRITE>
|
||||
writeResource(); // writing is performed
|
||||
// </WRITE>
|
||||
|
||||
// <EXIT>
|
||||
up(&resourceAccess); // release resource access for next reader/writer
|
||||
// </EXIT>
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
// <READ>
|
||||
readResource(); // reading is performed
|
||||
// </READ>
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
## 参考资料
|
||||
|
||||
- Tanenbaum A S, Bos H. Modern Operating Systems [M]. Pearson, 2014.
|
||||
- [Readers–writers problem - Wikipedia](https://en.wikipedia.org/wiki/Readers%E2%80%93writers_problem)
|
||||
Reference in New Issue
Block a user