写者优先问题
-
由于读-写、写-写互斥,使用信号量
file
控制临界区访问- 一群读者在读取时若有写者进来,会在队列占有
quemutex
,等待最后一个正在读的人离开释放file
,然后立刻开始写
- 一群读者在读取时若有写者进来,会在队列占有
-
使用一个
readcount
整型变量计数器,记录读者数量,用信号量rdcntmutex
控制该变量的访问;writecount
记录写者数量,需要信号量wrtcntmutex
控制该变量访问 -
为了实现写者优先,那么不能按照读者写者来的先后顺序排队,故设置两个队列,优先队列
quemutex
和读者等待队列readEntry
。- 当一个写者来时占用优先队列
quemutex
,一直占有到最后一个写者离开才能释放 - 当一个读者来时放到
readEntry
排队,若此时前面没有其他读者,也没有写者,它才可以进到quemutex
"就绪区",quemutex
仅允许一个读者存在 - 后续所有的读进程要统一放到
readEntry
等待。 - 直到所有的写进程都写完了,才会唤醒
quemutex
中的唯一读者,该读者完成任务后,才会唤醒readEntry
的第一个读者进入quemutex
(即quemutex
队列长度最多为2)
- 当一个写者来时占用优先队列
int readcount = 0, writecount = 0;
Semaphore file = 1, rdcntmutex = 1, wrtcntmutex = 1;
Semaphore quemutex = 1, readEntry = 1;
Reader(){
P(readEntry);
P(quemutex); // 若有写者占用que,后续读者会被卡在外面
P(rdcntmutex);
if (readcount == 0)
P(file); // 若是第一个读者进来,则占据临界区阻止写进程写
readcount++;
V(rdcntmutex);
V(quemutex);
V(readEntry);
// 读操作不用互斥保护
// reading operation
// 读完了,读者走人
P(rdcntmutex);
if (readcount == 1)
V(file); // 若是最后一个读者离开,则释放写进程的阻塞,允许写
readcount--;
V(rdcntmutex);
}
Writer(){
P(wrtcntmutex);
if (writecount == 0)
P(quemutex); // 一旦写者进入,则占用该优先队列
writecount++;
V(wrtcntmutex);
P(file); // 等待现存读者读完唤醒阻塞的写者
// writing, 写进程需要互斥保护
V(file);
P(wrtcntmutex);
if (writecount == 1)
V(quemutex);// 若源源不断有写者进入,writecount不会为0,也不会释放
writecount--; // 当最后一个写者离开,才会唤醒等在que的一个读者
V(wrtcntmutex);
}