一分钟解决读者和写者问题

长话短说,就是:读、读共享;写、写互斥;写、读互斥。

直接从代码角度分析:

  • 互斥信号量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的访问是互斥的。


看到这里,聪明的你可能已经发现问题了,如果一直有读进程在读,那么写进程就要一直等待下去,这样可能会导致写进程"饿死" 。而上述这种写法正是只满足了读进程优先原则的。

而对于 写进程优先 和 读写公平 的实现可以参考其他博文的讲解,感兴趣可以去了解一下,很有意思。