问答题
某火车订票系统,可供多个用户同时共享一个订票数据库。规定允许多个用户同时查询该数据库,有查询者时,用户不能订票;有用户订票而需要更新数据库时,不可以有其他用户使用数据库。请用P、V操作写出查询者和订票者的同步执行程序。
【正确答案】本题是一个典型的读者-写者问题,查询者是读者,订票者是写者。读者-写者问题的主要要求是:①允许多个读者共享对象。②不允许写者和其他读者或写者同时访问共享对象。为了达到上述控制,引入一个变量readcount,用于记录当前正在运行的读者进程数,以及读互斥信号量rmutex和写互斥信号量wmutex。每个读者进程进入系统后需对readcount加1。当readcount的值由0变为1时,说明是第一个读者进程进入,因此需要该读者进程对控制写者进程的信号量wmutex进行P操作,以便与写者进程互斥运行;当readcount的值由非0值增加时,说明不是第一个读者进程,此时控制写者进程的信号量已经过P操作,已经禁止写者进程进入,因此不需要再次对该信号量进行P操作。当读者进程退出时,需对readcount减1。如发现减1后readcount的值变为0,说明是最后一个读者进程退出,因此需要该读者进程对控制写者进程的信号量wmutex进行V操作,以便写者进程能够进入。同步程序描述如下:
Semaphore rmutex=1,wmutex=1;
Int readcount=0;
Inquirer()
{ //查询者进程
While(true)
{
P(rmutex);
If(readcount==0) P(wmutex);
//如果有查询者,不允许订票
readcount=readcount+1;
V(rmutex);
查询数据库;
P(rmutex);
readcount=readcount-1;
If(readcount==0) V(wmutex);
//最后一个查询者走后允许订票
V(rmutex);
}
}
Booker() //订票者进程
{
While(true)
{
P(wmutex);
使用数据库,订票;
V(wmutex);
}
}
下面改进要求,规定允许多个用户同时查询数据库,当有订票者到达时,不允许后续查询者查询数据库,且多个订票者可以互斥使用数据库。(即写者优先算法)描述如下:
Semaphore rmutex=wmutex=r=w=1;
//加入r、w两个信号量实现订票者优先
Int Readcount=0;
Int Writecount=0;
Inquirer()
{
While(true)
{
P(r); //需先检查有无订票者进程存在
p(rmutex);
If(readcount==0) P(w);
Readcount=readcount+1;
V(rmutex);
V(r);
查询数据库;
P(rmutex);
Readcount=readcount-1;
If(readcount==0) v(w); //无查询者进程存在
V(rmutex);
}
}
Booker()
{
While(true)
{
P(wmutex);
If(writecount==0) P(r);
//第一个订票者进程进入,不允许后续查询者进程进入
Writecount=writecount+1;
V(wmutex);
P(w);
使用数据库,订票;
V(w);
P(wmutex);
Writecount=writecount-1;
If (writecount==0) v(r);
//无订票者时允许查询者进入
V(wmutex);
}
}
这里r信号量用来控制读者进程的进入,如果有写者存在,则占用该信号量,阻止后续读者进入临界区;而w信号量则表示对临界区进行写操作的权力,当读者在临界区时,占用w信号量以阻止写者进行写操作,这里w的作用类似于刚才未添加新条件的解法中的wmutex信号量。本解法中,rmutex和wmutex信号量变为对读者、写者计数器进行互斥操作控制的信号量。
【答案解析】