阅读前提醒:本文代码为伪代码,仅供理解!
马上就要被关得精神失常了,也许这是我的最后一条博客了吧……()
啊哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈水文来咯!!!!!
1.什么是读者写者问题
简单来说,读者只对数据文件进行读取并不进行修改操作,读者和读者之间是不存在互斥的。
但是写者不一样,写者只有自己工作的时候时完成得最好的,但是他和其他进程一起工作的话是事倍功半的,因为写者与写者之间的想法是不一样的,如果他们要同时修改的话很容易导致数据冲突。又或者写者和读者一起工作,当读者刚好读取到写者正在修改的部分的时候,这个程序也将毫无意义。
2.优先的两种策略
①读者优先
总是给读者优先权,只要写者当前没有进行写的操作,读者就可以获得访问权。这样的优先策略主要应用于读者比较多且写者不需要经常更新的情况下,例如图书馆参考数据库。
②写者优先
通常把优先权交给写者,而将读者延迟到所有等待着的以及活动着的写者都完成了为止。这种情况主要应用于经常需要更新的系统,比如机票预订系统。
3.在写者优先策略之下
写者并不是拥有“绝对优先权”,写者不能无条件的打断读者的进程,他只能在进入队列后如果前面有正在工作的读者,要等待前一个读者结束了进程才能轮到他。
- 读者和写者、写者和写者不能同时访问缓冲区
- 无写进程时各读者可同时访问缓冲区
- 读者和写者都等待时,写者优先访问缓冲区。
4.实现设计
①先过一遍代码
reader()
{
while(true)
{
wait(read);//申请读取权限
wait(RCSignal)//多个读者互斥
if(!readCount)//如果读者队列为空,申请文件资源
wait(fileSrc);
readCount++;
signal(RCSignal);//释放互斥信号量
signal(read); //释放读取权限
……
perform read operation//执行读取操作代码
……
wait(RCSiganl);//多个读者互斥
readCount--;
if(!readCount) //如果读者队列为空,释放文件资源
signal(fileSrc);
signal(RCSignal);//释放互斥信号量
}
}
②进程优先级互斥的表现
- 因为写者读者互斥,所以我们引入第一个互斥信号量 read 并将之初始化为1
- 读者对read的操作:其中读者申请到read后,在读操作前立即释放
- 写者申请到了read后,占用其直至写者堵塞排队队列都完成工作
③临界资源的互斥
因为要实现进程对临界资源的互斥访问,所以我们引进信号量fileSrc
④读者写者等待进程数量
通过记录当前堵塞的写者进程数所以引入ReaderCount与Writer Count。相应的,因为ReaderCount与WriterCount也是可以被多个读者/写者进程访问的临界资源,因此我们也需要设置互斥信号量RCSignal与WCSignal。
⑤四个互斥信号量与两个变量
- 进程优先互斥:read=1
- 临界资源互斥:fileSrc=1
- 多个读者互斥:RCSignal=1
- 多个写者互斥:WCSiganl=1
- 读者在读数:ReaderCount=0
- 写者排队数:WriterCout=0
5.最终代码
①读者部分
reader()
{
while(true)
{
wait(read);//申请读取权限
wait(RCSignal)//多个读者互斥
if(!readCount)//如果读者队列为空,申请文件资源
wait(fileSrc);
readCount++;
signal(RCSignal);//释放互斥信号量
signal(read); //释放读取权限
……
perform read operation//执行读取操作代码
……
wait(RCSiganl);//多个读者互斥
readCount--;
if(!readCount) //如果读者队列为空,释放文件资源
signal(fileSrc);
signal(RCSignal);//释放互斥信号量
}
}
②写者部分
writer()
{
while(true)
{
wait(writeCountSignal);//申请写者计数器资源
if(!readCount)//如果当前写着队列为空则申请优先权限
wait(read);
writeCount++;
signal(writeCountSignal);//释放写者计数器资源
wait(fileSrc); //申请文件资源
……
perform write operation//执行写操作代码
……
signal(fileSrc);//释放文件资源
wait(writeCountSignal);//多个写者互斥
writeCount--;
if(!writeCount) //如果写者队列为空,则允许读者进行操作
signal(read);读者
signal(writeCountSignal);//释放互斥信号量
}
}
水完了……爬走了……886……