长话短说,就是:读、读共享;写、写互斥;写、读互斥。
直接从代码角度分析:
- 互斥信号量wmutex: 实现Reader与Writer进程间在读和写、写和写时的互斥
- 整型变量readcount: 表示正在读的进程数目
- 互斥信号量rmutex在下文揭秘
cpp
semaphore rmutex=1,wmutex=1;
int readcount=0;
void Reader()
{
while(1)
{
wait(rmutex);
if(readcount==0)
wait(wmutex);
readcount++;
signal(rmutex);
读文件;
wait(rmutex);
readcount--;
if(readcount==0)
signal(wmutex);
signal(rmutex);
}
}
void Writer()
{
while(1)
{
wait(wmutex);
写文件;
signal(wmutex);
}
}
分析:
【1】首先对于互斥信号量wmutex。因为在同一文件上,读和写不能共存,写和写不能共存,需要互斥访问。
【2】然后对于整型变量readcount。我把重要的话说在前面:这是实现读、读共享的关键。因为readcount用来表示正在读进程的数目,一开始第一个读进程进来,因为readcound == 0,所以执行wait(wmutex),然后再执行readcount++,当第二个读进程进来时,因为readcount == 1 ,所以不用再执行wait(wmutex),这样就实现了多个读进程共享同一文件。最后当readcount == 0时,表示已无读进程在读文件,然后执行signal(wmutex),那么写进程才能获得资源进行写操作。
【3】互斥信号量rmutex的解释:若此时有两个读进程并发执行,则 readcount=0 时两个进程也许都能满足if条件, 都会执行wait(wmutex), 从而使第二个读进程阻塞的情况(比如第一个读进程还没来的急执行readcount++,第二个进程就已经通过if (readcount == 0)的判断,然后被阻塞了)。而出现上述问题的原因在于对readcount变量的检查和赋值无法一气呵成, 因此可以设置另一个互斥信号量rmutex来保证各读进程对readcount的访问是互斥的。
看到这里,聪明的你可能已经发现问题了,如果一直有读进程在读,那么写进程就要一直等待下去,这样可能会导致写进程"饿死" 。而上述这种写法正是只满足了读进程优先原则的。
而对于 写进程优先 和 读写公平 的实现可以参考其他博文的讲解,感兴趣可以去了解一下,很有意思。