一.问题描述
- 有读者、写者两组并发进程,共享一个文件
- 允许多个读者同时对文件执行读操作
- 任一写者在完成写操作之前都不允许其他读者和写者工作
- 写者执行写操作前,应该让已有的读者和写者全部退出
二.问题分析
- 互斥关系1:写进程和写进程
- 互斥关系2:写进程和读进程
- 读进程和读进程之间不存在互斥问题
- 写进程和任何进程都互斥,设置一个互斥信号量rw在写者访问共享文件前后执行P、V操作
- 读进程和写进程也要互斥,因此读者在访问共享文件前后也要对rw执行P、V操作,但是这就导致读者和读者也不能同时访问共享文件
- 因此我们可以让第一个访问共享文件的读进程上锁,让最后一个访问完共享文件的读进程解锁,通过设置变量count来记录当前有几个读进程在访问文件:
在这个过程中,读进程先判断自己是不是第一个读进程(count=0),如果是那么先对文件上锁(P(rw)),然后再使得count++,也就是访问文件的读进程数+1,然后开始读文件,在读完文件之后,先进程count-1,表示访问文件的读进程数-1,最后再判断自己是否是最后一个进程,如果是则对文件解锁(V(rw))
- 但是此时如果有两个读进程并发执行,在进程1判断完count=0时正准备对文件进行上锁,此时正好发生了进程切换,进程2也发现count=0,然后对文件进行了上锁,此时再切换回进程1,进程1会发现文件已经被上锁,这就会使得进程1阻塞。
出现上述问题的原因是:对count的检查和对文件的上锁没有一气呵成 - 因此我们可以设置另一个互斥信号量mutex来保证各进程对count的访问是互斥的:
潜在的问题:只要有读进程还在读,写进程就要一直阻塞等待,可能会出现饿死现象,因此这种算法中,读进程是优先的
- 如果要实现“写优先”,那么就再加一个互斥信号量w:
三.小结
读者-写者问题最核心的部分就是通过设置计数器count变量来记录当前访问文件的读进程的数量,我们可以通过count判断当前进入的读进程是否是第一个/最后一个读进程,从而做出不同的处理,实现读进程可以和读进程一起访问共享文件