前言
这是我参与「第四届青训营 」笔记创作活动的第22天,在上一篇笔记中,我们讨论了读者写者冲突问题的具体描述和思考,也对读写冲突问题给出了一种读者优先的解决方法,并对该方法做了总结与分析。在这里,我想讨论一下一种写进程“相对优先”的算法。
写进程相对优先
(1)写进程优先的解决思路
若我们希望写者进程优先,即如果此时有读者进程正在读共享文件,同时有写进程请求访问该共享文件,那么此时应禁止后续的读者进程的要求,当此时已在使用共享文件的读进程执行完毕后,立即让写进程对共享文件执行相应操作,并且保证只有在无任何写进程执行的情况下才允许读者进程再次运行。为此,我们可以增加一个信号量w来实现“写优先”,并在上一篇笔记的PV程序的writer()和reader()函数中各增加一对PV操作,这样就可以完成“写优先”的算法。
(2)PV代码展示
int count = 0; //记录当前读者数量
semaphore mutex = 1; //保护count变量,用于互斥
semaphore rw = 1; //读写互斥,用来互斥访问共享文件
semaphore w = 1; //用于实现“写优先”
writer(){
while(1){
** P(w);
//由于写者进程相互之间是互斥的,因此某个写进程只有在当前无写进程的情况下才可访问该共享文件
//同时禁止后续其他写进程访问该共享文件**
P(rw); //互斥访问共享文件
writing;
V(rw); //释放共享文件
** V(w); //恢复共享文件的访问权限**
}
}
reader(){
while(1){
**p(w); //读写进程互斥,在无写进程时读进程访问该共享文件**
P(mutex); //互斥访问count变量
if(count == 0) //第一个读进程访问共享文件
P(rw); //阻止写进程
count++; //读者+1
V(mutex); //释放互斥变量count
**//这里先释放互斥变量count,后释放“写优先”信号量w,是因为读进程不对共享文件作出修改,
//因此读进程保持了可以排队的特性**
** V(w); //恢复对共享文件的访问权限**
reading;
P(mutex); //互斥访问count变量
count--;; //读者-1
if(count == 0)
V(rw); //允许写进程写
V(mutex); //允许后续读者进程修改count变量
}
}
总结分析
- 如果我们仔细思考,会发现这里的写进程是“相对优先”的。当某个写进程要访问共享文件时,若此时先有一些读进程要求访问,而后有另一个写进程又要求访问该文件,则在当前访问文件的写进程结束对该文件的写操作后,会是一个读进程而不是一个写进程占用该文件。
- 这是为什么呢?我们观察信号量w,在信号量w的阻塞队列上,因为读进程先来,因此读进程排在该共享文件阻塞队列的队首,而V操作唤醒进程时唤醒的正是队首进程。所以在这个算法中,写进程优先是相对而言的,有些书中将这个算法称为“读写公平法”。