读者 - 写者问题
问题描述
一个数据文件或记录,可被多个进程共享,但仅允许进程要么做“读操作”,要么做“写操作“,不允许进程同时进行读写操作。
问题分析
读者到来时:
- 若没有进程访问临界区,读者可以进入
- 若有读者在访问临界区,有写者在等待,读者可以进入(读者优先)
- 若有写者在访问临界区,读者等待
写者到来时:
- 若没有进程访问临界区,写者可以进入
- 若有进程在访问临界区,写者等待
总结:
- 读者与读者之间不互斥(无关系)
- 读者与写者之间互斥
- 读者与读者之间互斥
记录型信号量解决
实现思路
- 因为写者进程与其他进程均为互斥关系,故设置互斥信号量:wmutex,来实现写者进程的互斥
- 因为读者进程之间可以同时访问资源,所以可以设置整型变量:readcount,用于记录目前共同访问资源的读者进程数目
- 因为添加:readcount整型变量,其可以同时被一个或多个读者进程访问,故此时readcount成为了临界资源。为了实现readcount的互斥访问,引入互斥信号量:rmutex
- 因为通过分析存在,读者优先的条件,故读者进程对互斥信号量wmutex的影响应该是:读者进程的第一个(readcount == 0)对wmutex进行上锁,读者进程的最后一个(readcount == 0)对wmutex进行解锁
代码实现
semaphore wmutex = 1, rmutex = 1; int readcount = 0 void reader(){ do{ wait(rmutex); //readcount的互斥访问 if(readcount == 0) //第一个读者进程对wmutex上锁 wait(wmutex); readcount++; signal(rmutex); …… perform read operation; …… wait(rmutex); readcount--; if(readcount == 0) //最后一个读者进程对wmutex解锁 signal(wmutex); signal(rmutex); }while(TRUE); } void writer(){ do{ wait(wmutex); …… perform write operation; …… signal(wmutex); }while(TRUE); } void main(){ cobegin; writer(); reader(); coend; }
信号量集解决
增加问题难度:限制同时访问资源的读者数目,假设同时最多访问资源的读者数目为RN
实现思路
- 为了实现读者数目的限制,引入信号量L,并对其赋予初值RN。Swait(L, 1, 1),每次一个读者进程访问,便会使得L减一,最低值不得小于1,便可决定,一次最多只能有RN个读者进程;此操作便可代替readcount的一系列操作
- 引入开关信号量:mx,当mx = 1,表示无写操作,若读进程进入,则不消耗mx,保证其余读者进程可以进入;若写进程进入,消耗mx,当mx = 0,表示正在进行写操作,其余进程均不能进入
- Swait(mx, 1, 1; L, RN, 0):写者进程的wait,表示目前没有写进程,L = RN 同时也没有任何一个读进程
代码实现
int RN; semaphore L = RN, mx = 1; void reader(){ do{ Swait(L, 1, 1); Swait(mx, 1, 0); //不消耗mx …… perform read operation; …… Ssignal(L, 1); }while(TRUE); } void writer(){ do{ Swait(mx, 1, 1; L, RN, 0); …… perform write operation; …… Ssignal(mx, 1); }while(TRUE); } void main(){ cobegin; reader(); writer(); coend; }