问答题 某火车订票系统,可供多个用户同时共享一个订票数据库。规定允许多个用户同时查询该数据库,有查询者时,用户不能订票;有用户订票而需要更新数据库时,不可以有其他用户使用数据库。请用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信号量变为对读者、写者计数器进行互斥操作控制的信号量。
【答案解析】