读者一写者问题是一个用信号量实现的经典进程同步问题。在系统中,一个数据集( 如文件或记录) 被几个并发进程共享,这些线程分两类,一部分只要求进行复操作,称之为“读者”;另一类要求写或修改操作,我们称之为“写者“。
一般而言,对一个数据集,为了保证数据的完整性、正确性,允许多个读者进程同时访问,但是不允许一个写者进程同其它任何一个进程(读者或者写者)同时访问,而这类问题就称之为”读者-写者“问题。
读者优先的算法在操作系统相关的书籍中都有介绍,这是一种最简单的解决办法:当没有写进程正在访问共享数据集时,读进程可以进入访问,否则必须等待。而读者优先的算法存在“饿死写者”线程的问题:只要有读者不断到来,写者就要持久地等待,直到 所有的读者都读完且没有新的读者到来时写者才能写数据集。而在很多情况下我们需要避免”饿死写者“,故而采用写者优先算法:
在写者优先算法中,我们要实现的目标是:
1.要让读者与写者之间、以及写者与写者之问要互斥地访同数据集;
2.在无写进程到来时各读者可同时访问数据集;
3.在读者和写者都等待时访问时写者优先.
一种算法实现:
我们将用两个不同的互斥信号量分别实现读者与写者间的互斥及各写者进程间的互斥:以互斥信号量Wmutex实现各写者问的互斥,互斥信号量Rmutex实现各读者与写者问的互斥;
设置两个整型变量Wcount和Rcount分别记录等待的写者数和正在读的读者数,因Wcount、Rcount都是共享变量,因此还要设置两个互斥信号量Mutl和Mut2以实现进程对这两个变最的互斥访问.
用信号量机制实现的写者优先的算法如 :
- Var Mut1,Mut2,Wmutex,Rmutex:Semaphore;
- Rcount,Wcount:integer;
- Mut1:=Mut2:=WMutex:=RMutex:=1;
- Rcount:=Wcount:=0;
- Writer:begin
- Wait(Mut1);
- Wcount:=Wcount+1;
- If Wcount=1 then Wait(Rmutex);
- Signal(Mut1);
- Wait(WMutex);
- 写操作;
- Wait(Mut1);
- Wcount:=Wcount-1;
- If Wcount=0 then Signal(Rmutex);
- Signal(Wmutex);
- Signal(Mut1);
- end
- Reader:begin
- Wati(Mut1);
- Signal(Mut1);
- Wait(Mut2);
- Rcount:=Rcount+1;
- If Rcount=1 then Wait(Rmutex);
- Signal(Mut2);
- 读操作;
- Wait(Mut2);
- Rcount:=Rcount-1;
- If Rcount=0 then Signal(Rmutex);
- Singal(Mut2);
- end