问题描述
有读者和写者两组并发进程,共享一个文件,当两个或以上的读进程同时访问共享数据时不会产生副作用,但若某个写进程和其他进程(读进程或写进程)同时访问共享数据时则可能导致数据不一致的错误。因此要求:①允许多个读者可以同时对文件执行读操作;②只允许一个写者往文件中写信息;③任一写者在完成写操作之前不允许其他读者或写者工作;④写者执行写操作前,应让已有的读者和写者全部退出。
读优先:
semaphore mutex = 1;//用于保护更新count变量时的互斥
semaphore rw = 1;//用于保证读者和写者互斥地访问文件
int count = 0;//用于记录当前的读者数量
void read(){
while(1){
P(mutex);
if(count == 0) //当第一个读进程读共享文件时,阻止写进程写
P(rw);
++count;
V(mutex);
read_data();
P(mutex);
--count;
if(count == 0) //当最后一个读进程读完共享文件,允许写进程写
V(rw);
V(mutex);
}
}
void write(){
while(1){
P(rw);
write_data();
V(rw);
}
}
在上面的算法中,读进程是优先的,也就是说,当存在读进程时,写操作将被延迟,并且只要有一个读进程活跃,随后而来的读进程都将被允许访问文件。这样的方式下,会导致写进程可能长时间等待,且存在写进程“饿死”的情况。
写优先
如果希望写进程优先,即当有读进程正在读共享文件时,有写进程请求访问,这时应禁止后续读进程的请求,等待到已在共享文件的读进程执行完毕则立即让写进程执行,只有在无写进程执行的情况下才允许读进程再次运行。为此,增加一个信号量并且在上面的程序中 writer()和reader()函数中各增加一对PV操作,就可以得到写进程优先的解决程序。
semaphore read_mutex = 1;
semaphore write_mutex = 1;
semaphore rw = 1;
semaphore w = 1; //用于实现“写优先”
int read_count = 0;
int write_count = 0;
void read() {
while (1) {
P(w); //在无写进程请求时进入
P(read_mutex);
if (read_count == 0)
P(rw);
++read_count;
V(read_mutex);
V(w); //恢复对共享文件的访问
read_data();
P(read_mutex);
--read_count;
if (read_count == 0)
V(rw);
V(read_mutex);
}
}
void write() {
while (1) {
P(write_mutex);
if (write_count == 0)
P(w); //请求写
write_count++;
V(write_mutex);
P(rw);
write_data();
V(rw);
P(write_mutex);
--write_count;
if (write_count == 0)
V(w);
V(write_count);
}
}
公平竞争:
semaphore mutex = 1;
semaphore rw = 1;
semaphore key = 1; //用于实现“公平竞争”
int count = 0;
void read(){
while(1){
P(key); //在无写进程请求时进入
P(mutex);
if(count == 0)
P(rw);
++count;
V(mutex);
V(key); //恢复对共享文件的访问
read_data();
P(mutex);
--count;
if(count == 0)
V(rw);
V(mutex);
}
}
void write(){
while(1){
P(key); //请求写
P(rw);
write_data();
V(rw);
V(key);
}
}