问题描述
一个数据文件或记录,可被多个进程共享,但仅允许进程要么做“读操作”,要么做“写操作“,不允许进程同时进行读写操作。
问题分析
读者到来时:
- 若没有进程访问临界区,读者可以进入
- 若有读者在访问临界区,有写者在等待,读者可以进入(读者优先)
- 若有写者在访问临界区,读者等待
写者到来时:
- 若没有进程访问临界区,写者可以进入
- 若有进程在访问临界区,写者等待
总结:
- 读者与读者之间不互斥(无关系)
- 读者与写者之间互斥
- 读者与读者之间互斥
记录型信号量解决
实现思路
- 因为写者进程与其他进程均为互斥关系,故设置互斥信号量: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;
}