信号量经典问题————读者写者不同优先级问题
读者写者问题
读写互斥,写写互斥,读读可并发
读者优先
- 当读者写者都在等待时,只有所有读者都读完,写者才能写
信号量:w=1(可写),mutex=1(可读)
共享变量:rcount=0(读者数量)
//伪代码
int rcount=0
semaphore w=1,mutex=1
reader(){
P(mutex);
rcount++;
if(rcount==1)
P(w);//堵塞写者,保证所有读者读完
V(mutex);
//以上保证所有读者都可同时读
//Read()
P(mutex);
rcount--;
if(rcount==0)
V(w);
V(mutex);
}
writer(){
P(w);
//write()
V(w);
}
存在问题,读者过多,饿死写者(rcount减少同时也在增加)。
写者优先
- 写者读者都在等待时,只有所有写者写完后,读者才能获得读权限
增加wcount标记写者存在,如果同时存在读写者,读者在执行时通过P(w)阻塞写者,而写者wcount标记存在,通过P(r)防止读者继续加入。
P(x)与V(x)用以保护原子操作
int wcount=0,rcount=0;
semaphore w=1,r=1,x=1;
reader(){
P(r);
P(x);
rcount++;
if(rcount==1)
P(w);
V(x);
V(r);
//Read()
P(x);
rcount--;
if(rcount==0)
V(w);
V(x);
}
writer(){
P(x);
wcount++;
if(wcount==1)
P(r);
V(x);
P(w);
//Write()
V(w);
P(x);
wcount--;
if(wcount==0)
V(r);
V(x);
}
- 对于写着优先问题,我也看了一些文章,觉得以下这个也很好
进程同步的经典问题1——读者写者问题(写者优先与公平竞争)
可以参考,这是代码
semaphore fmutex=1, rdcntmutex=1, wtcntmutex=1, queue=1;
//fmutex --> access to file; rdcntmutex --> access to readcount
//wtcntmutex --> access to writecount
int readcount = 0, writecount = 0;
void reader(){
while(1){
wait(queue);
wait(rdcntmutex);
if(0 == readcount)wait(fmutex);
readcount = readcount + 1;
signal(rdcntmutex);
signal(queue);
//Do read operation ...
wait(rdcntmutex);
readcount = readcount - 1;
if(0 == readcount)signal(fmutex);
signal(rdcntmutex);
}
}
void writer(){
while(1){
wait(wtcntmutex);
if(0 == writecount)wait(queue);
writecount = writecount + 1;
signal(wtcntmutex);
wait(fmutex);
//Do write operation ...
signal(fmutex);
wait(wtcntmutex);
writecount = writecount - 1;
if(0 == writecount)signal(queue);
signal(wtcntmutex);
}
}
增加一个排队信号量:queue。读写进程访问文件前都要在此信号量上排队,通过区别对待读写进程便可达到提高写进程优先级的目的。另外再增加一个 writecount 以记录提出写访问申请和正在写的进程总数.
每个读进程最开始都要申请一下 queue 信号量,之后在真正做读操作前即让出(使得写进程可以随时申请到 queue)。而只有第一个写进程需要申请 queue,之后就一直占着不放了,直到所有写进程都完成后才让出。等于只要有写进程提出申请就禁止读进程排队,变相提高了写进程的优先级。