面向对象OS读者-写者问题

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

2.读者—写者问题

读者—写者问题(Readers-Writers problem)也是一个经典的并发程序设计问题,是经常出现的一种同步问题。计算机系统中的数据(文件、记录)常被多个进程共享,但其中某些进程可能只要求读数据(称为读者Reader);另一些进程则要求修改数据(称为写者Writer)。就共享数据而言,Reader和Writer是两组并发进程共享一组数据区,要求:

(1)允许多个读者同时执行读操作;

(2)不允许读者、写者同时操作;

(3)不允许多个写者同时操作。

Reader和Writer的同步问题分为读者优先、弱写者优先(公平竞争)和强写者优先三种情况,它们的处理方式不同。

(1)读者优先。对于读者优先,应满足下列条件:

如果新读者到:

①无读者、写者,新读者可以读;

②有写者等待,但有其它读者正在读,则新读者也可以读;

③有写者写,新读者等待。

如果新写者到:

①无读者,新写者可以写;

②有读者,新写者等待;

③有其它写者,新写者等待。

单纯使用信号量不能解决读者与写者问题,必须引入计数器rc 对读进程计数;

rc_mutex 是用于对计数器rc 操作的互斥信号量;write表示是否允许写的信号量;于是读者优先的程序设计如下:

int rc=0; //用于记录当前的读者数量

semaphore rc_mutex=1; //用于对共享变量rc 操作的互斥信号量

semaphore write=1; //用于保证读者和写者互斥地访问的信号量

void reader() /*读者进程*/

do{

P(rc_mutex); //开始对rc共享变量进行互斥访问

rc ++; //来了一个读进程,读进程数加1

if (rc==1) P(write);//如是第一个读进程,判断是否有写进程在临界区,

//若有,读进程等待,若无,阻塞写进程

V(rc_mutex); //结束对rc共享变量的互斥访问

读文件;

P(rc_mutex); //开始对rc共享变量的互斥访问

r c--; //一个读进程读完,读进程数减1

if (rc == 0) V(write);//最后一个离开临界区的读进程需要判断是否有写进程//需要

进入临界区,若有,唤醒一个写进程进临界区

V(rc_mutex); //结束对rc共享变量的互斥访问

} while(1)

void writer() /*写者进程*/

do{

P(write); //无读进程,进入写进程;若有读进程,写进程等待写文件;

V(write); //写进程完成;判断是否有读进程需要进入临界区,

//若有,唤醒一个读进程进临界区

} while(1)

读者优先的设计思想是读进程只要看到有其它读进程正在读,就可以继续进行读;写进程必须等待所有读进程都不读时才能写,即使写进程可能比一些读进程更早提出申请。该算法只要还有一个读者在活动,就允许后续的读者进来,该策略的结果是,如果有一个稳定的读者流存在,那么这些读者将在到达后被允许进入。而写者就始终被挂起,直到没有读者为止。

(2)写者优先1。为了解决以上问题,写者优先1的设计思想是在一个写者到达时如果有正在工作的读者,那么该写者只要等待正在工作的读者完成,而不必等候其后面到来的读者就可以进行写操作。注意,该算法当一个写者在等待时,后到达的读者是在写者之后被挂起,而不是立即允许进入。

在读者优先的算法的基础上增加了一个排队信号量read,读、写进程在每次操作前都要等待read信号量。写者优先1的程序设计如下:

int rc=0; //用于记录当前的读者数量

semaphore rc_mutex=1; //用于对共享变量rc 操作的互斥信号量

semaphore write=1; //用于保证读者和写者互斥地访问的信号量

semaphore read=1; //用于保证在写进程封锁其后续的读进程的信号量

void reader() /*读者进程*/

do{

P(read); //若有写进程,后续读进程等待,在read队列上排队P(rc_mutex); //开始对rc共享变量进行互斥访问

rc++; //来了一个读进程,读进程数加1

if rc=1 then P(write); //第一个读进程需要判断是否有写进程在临界区,若有,

//读进程需要等待,若没有,阻塞写进程

V(rc_mutex); //结束对rc共享变量的互斥访问

V(read);//从read队列中唤醒一个进程

Reading the file;

P(rc_mutex); //开始对rc共享变量的互斥访问

rc--; //一个读进程读完,读进程数减1

if rc=0 then V(write); //最后一个离开临界区的读进程需要判断是否有写进程

/ //需要进入临界区,若有,唤醒一个写进程进临界区V(rc_mutex); //结束对rc共享变量的互斥访问

}

void writer() /*写者进程*/

do{ P(read); //无读进程,写进程进入;有读进程,在read排队,其后

//到来的读进程排在该队列写者之后

P(write); //若有读进程在读,等待现有读进程读完才可写

Writeing the file;

V(write); //写进程完成;判断是否有读进程需要进入临界区,若有,

//唤醒一个读进程进临界区

V(read); //从read队列中唤醒一个进程

注意,该算法当第一个写者已经P(read)后,read变为0,来了N个读者,他们都停留在它的P(read)这一句。那么会出现什么问题呢?此时,如果原来的写者完成了,紧接又来了一个写者,写者需要P(read)。这个时候,由于N个读者都已经在这个写者之前P(read)了,所以这个写者需要排队排在这N个读者分别都得到P(read)后才能得到执行,这个就不是写者优先了,而是读者写者公平竞争。

相关文档
最新文档