读者-写者问题
读者-写者两组并发进程,共享一个文件,当两个或两个以上的读进程同时访问共享数据时,不会产生副作用,单如果某个写进程和其他进程(读和写)同时访问共享数据则可能导致数据不一致的错误。
因此要求:
1.允许多个读者可以同时对文件执行读操作
2.只允许一个写者往文件中写信息
3.任意一个写者在完成写操作之前不允许其他读者或者写者工作
4.写者执行写操作之前,应让已有的读者和写者全部退出
读者进程
与消费者进程不同,读者进程在读取数据之后,不会将数据清空。并不会改变数据,因此它们可以同时访问共享数据。
两类进程 :写进程,读进程
互斥关系:
【写进程-写进程】互斥
【写进程-读进程】互斥
【读进程-读进程】不存在互斥关系
semaphore rw=1;//用于实现对共享文件的互斥访问
int count=0;
writer(){
while(true){
P(rw);
写;
V(rw);
}
}
reader(){
while(true){
if (count==0){//第一个读进程负责在读之前枷锁
P(rw);
}
count++;//访问数量+1
读文件;
count--;//访问数量-1
if(count==0)//有最后一个读进程负责读完后解锁
V(rw);
}
}
但是如果两个进程并发执行,count=0的时候,两个进程有可能都能满足if条件,都会执行P(rw).如此第二个读进程就会阻塞
因此我们想到了一个办法,我们让进程互斥访问count
semaphore rw=1,mutex=1;//用于实现对共享文件的互斥访问
int count=0;
writer(){
while(true){
P(rw);
写;
V(rw);
}
}
reader(){
while(true){
P(mutex);
if (count==0){//第一个读进程负责在读之前枷锁
P(rw);
}
count++;//访问数量+1
V(mutex);
读文件;
P(mutex);
count--;//访问数量-1
if(count==0)//有最后一个读进程负责读完后解锁
V(mutex);//互斥访问count(释放)
V(rw);
}
}
但是这样又有一个问题,只要读进程一直在读,写进程就会一直在阻塞等待,有可能会被饿死,因此,在这种算法中,读进程是优先的,而我为了不让这个情况发生
semaphore rw=1,mutex=1;//用于实现对共享文件的互斥访问
int count=0;
semephore w=1//变量用于实现写优先
writer(){
while(true){
P(w);
P(rw);
写;
V(rw);
V(w);
}
}
reader(){
while(true){
P(w);
P(mutex);
if (count==0){//第一个读进程负责在读之前枷锁
P(rw);
}
count++;//访问数量+1
V(mutex);
V(w);
读文件;
P(mutex);
count--;//访问数量-1
if(count==0)//有最后一个读进程负责读完后解锁
V(mutex);//互斥访问count(释放)
V(rw);
}
}
这样当 读者1-》写者1-〉读者2的时候
读者1进程:
会让w变成0再变成1,会让rw变成0
写者1进程:
会把w变成0,但是会因为rw为0而被阻塞
读者2进程:
会因为w为0而被阻塞
读者1完成读后
rw变成1,激活写者1的写文件代码
写者1完成写后
w变成1,读者2被激活
结论:这种算法连续进入的多个读者可以同时读文件,但是写者不难喝进他进程同时访问文件,而且写者不会饥饿,但是这个也不是真正的写优先,而是相对公平的FCFS
部分教材将其称为“读写公平法”