操作系统课程设计.docx
《操作系统课程设计.docx》由会员分享,可在线阅读,更多相关《操作系统课程设计.docx(13页珍藏版)》请在冰点文库上搜索。
操作系统课程设计
设计1题目进程同步(读者-写者问题)
一、问题描述与分析
一个数据文件或记录,可被多个进程共享,我们把只要求读该文件的进程称为“Reader”进程,其他进程则称为“Writer进程”允许多个进程同时读一个共享对象,因为读操作不会使数据文件混乱。
但不允许一个Writer进程和其他Reader进程或Writer进程同时访问将会引起混乱。
所谓读者写者问题,是指保证一个writer进程必须与其他进程互斥地访问共享对象的同步问题。
读者写者问题可以这样的描述,有一群写者和一群读者,写者在写同一本书,读者也在读这本书,多个读者可以同时读这本书,但是,只能有一个写者在写书,并且,读者必写者优先,也就是说,读者和写者同时提出请求时,读者优先。
当读者提出请求时需要有一个互斥操作,另外,需要有一个信号量S来当前是否可操作。
二、设计要求和目的
1.设计要求
通过解决读者写者问题实现进程同步。
即
(1)实现写-写互斥,
(2)读-写互斥(3)读-读允许(4)写者优先
2.设计目的
(l).用信号量来实现读者写者问题,掌握进程同步机制及其实现机理。
(2).理解和运用信号量、PV原语、进程间的同步互斥关系等基本知识。
三、背景知识
1.参考操作系统课本中关于进程同步这方面的知识以及结合老师上课的讲解,仔细研究利用信号量实现读写者问题。
读者写者问题的定义如下:
有一个许多进程共享的数据区,这个数据区可以是一个文件或者主存的一块空间;有一些只读取这个数据区的进程(Reader)和一些只往数据区写数据的进程(Writer),此外还需要满足以下条件:
(1) 任意多个读进程可以同时读这个文件;
(2) 一次只有一个写进程可以往文件中写;
(3) 如果一个写进程正在进行操作,禁止任何读进程度文件。
我们需要分两种情况实现该问题:
读优先:
要求指一个读者试图进行读操作时,如果这时正有其他读者在进行操作,他可直接开始读操作,而不需要等待。
写优先:
一个读者试图进行读操作时,如果有其他写者在等待进行写操作或正在进行写操作,他要等待该写者完成写操作后才开始读操作。
本实验主要实现的是写者优先。
2.去图书馆借了对此方面有所介绍的书籍,从网上查询解决设计过程中遇到的疑难问题,实现设计功能。
如进程的创建pcb[Count]=newPCB();//申请进程控制块
pcb[Count].Id=Count+1;
pcb[Count].Name="读者1";
sequnce.add(pcb[Count]);
Count++;
实现创建读者进程
四、概要设计
1.为了实现读者和写者的读写过程,将每个读者和每个写者作为了一个单独的线程,所以设置了两个类,一个是读者类Reader,一个是写者类Writer.
2.为了实现读者写者之间的写-写互斥,读-写互斥,读-读允许,需要另外一个类Database,类中分别用关于读者的方法和写者的方法来控制读写之间的这种关系.
(1)创建读写者类
publicclassReaderextendsThread{}创建读者类
publicclassWriterextendsThread{}创建写者类
(2)分别设置写者、读者的两个方法,开始写和结束写开始读和结束读
publicsynchronizedintstartRead()开始读
publicsynchronizedintendReading()结束写
publicsynchronizedvoidstartWriting()开始写
publicsynchronizedvoidendWriting()结束读
方法中用读者布尔变量dbReading和写者布尔变量dbWriting控制读写者之间的关系,具体的控制过程在详细设计中会体现
(3)在操作系统总的main类中为读者写者创建进程。
pcb[Count]=newPCB();//申请进程控制块创建读者进程
pcb[Count].Id=Count+1;
pcb[Count].Name="读者1";
sequnce.add(pcb[Count]);
Count++;
pcb[Count]=newPCB();//申请进程控制块创建写者进程
pcb[Count].Id=Count+1;
pcb[Count].Name="写者1";
sequnce.add(pcb[Count]);
Count++;
五、详细设计
为了实现读者和写者的读写过程,将每个读者和每个写者作为了一个单独的线程,所以设置了两个类,一个是读者类Reader,一个是写者类Writer.以读者类为例:
一个读者的动作过程为由睡眠->等待->开始读->结束读->睡眠的一个循环过程,而一个写者的动作过程也为此.
读者调用方法napping()进行等待,调用startRead()方法开始读,最后在调用endReading()方法结束读入,释放运行空间.写者同读者.
但是为了实现读者写者之间的写-写互斥,读-写互斥,读-读允许,需要另外一个类Database,类中分别用关于读者的方法和写者的方法来控制读写之间的这种关系.
首先要实现睡眠的方法napping(),读者和写者在睡眠过程都应该是一样的,只是他们睡眠的时间不同,所以只需写出一个方法:
publicstaticvoidnapping(){
intsleepTime=(int)(NAP_TIME*Math.random());
try{
Thread.sleep(sleepTime*1000);
}catch(Exceptione){
e.printStackTrace();
}
}
在方法中,控制线程休眠随机的时间,由于每个读者或写者都是一个线程,而每个读者或写者他们工作休眠的时间都不一定相同,他们请求工作的时间也不一定相同,所以取了随机时间
其次设置了读者的两个方法,开始读和结束读,由于这只是个模拟读写问题,所以只需要知道结果就行,就不用显示出他是怎么读的.
在开始读中,当有写者在写时,读者需要等待wait(),在没有人在工作时,如果有写者和读者同时请求,那么就让写者先进,这是写者优先.所以这就归纳于一种情况,当读者布尔变量dbReading为FALSE时,如果有需要工作的写者,那么读者就等待.当读者请求读入后,计数有多少读者需要工作的变量readerCount+1,如果这是第一个进入工作的读者就需要将显示是否有读者在工作的读者布尔变量变为TRUE.
publicsynchronizedintstartRead(){
if(dbReading==false){
while(writerCount>0){
try{
System.out.println("readeriswaiting");
wait();
}catch(Exceptione){
System.out.println(e.toString());
e.printStackTrace();
}
}
}
++readerCount;
if(readerCount==1){
dbReading=true;
}
returnreaderCount;
}
读结束时,计数需要读的读者数-1,然后释放出空间给需要工作的人.
publicsynchronizedintendReading(){
--readerCount;
if(readerCount==0){
dbReading=false;
}
notifyAll();//释放出空间
System.out.println("onereaderisdone,reading.Count="+readerCount);
returnreaderCount;
}
第三,编写关于写者的开始写和结束写方法,在开始写方法中,首先要将计数需要写的变量writerCount+1,写者如果有读者或者有写者正在工作,那么就等待,如果没有就直接进入写,然后表示是否有写者在写的布尔变量dbWriting变为TRUE
publicsynchronizedvoidstartWriting(){//控制写者开始进入写
++writerCount;
while(dbReading==true||dbWriting==true){
try{
System.out.println("Writeriswaiting");
wait();
}catch(Exceptione){
System.out.println(e.toString());
}
}
dbWriting=true;
}
结束时只需将writerCount-1和dbWriting为FALSE,然后释放出空间.
PublicsynchronizedvoidendWriting(){//控制写者结束写入
--writerCount;
dbWriting=false;
System.out.println("onewriterisdone,writing.Count="+writerCount);
notifyAll();
}
读者:
是
否
是
否
写者:
是
否
六、结果分析
点击“进程同步”
全部结果如下:
reader1issleeping
reader3issleeping
reader4issleeping
reader4wantstoread//reader4请求读
reader4isreading.Count=1//reader4正在读
Writer2issleeping
Writer1issleeping
reader2issleeping
Writer1wantstowrite//Writer1请求写
Writeriswaiting//实现进程互斥,Writer1等待
reader2wantstoread
reader2isreading.Count=2//rearder2可以直接读
onereaderisdone,reading.Count=1//一个读进程结束,正在读的进程还有一个
Itisreader2whohasdonereadingaccordingtocount=1//告知是进程reader2结束
Writeriswaiting
reader1wantstoread
reader1isreading.Count=2
Writer2wantstowrite
Writeriswaiting
reader3wantstoread
reader3isreading.Count=3
onereaderisdone,reading.Count=2
Itisreader3whohasdonereadingaccordingtocount=2
Writeriswaiting
Writeriswaiting
onereaderisdone,reading.Count=1
Itisreader4whohasdonereadingaccordingtocount=1
Writeriswaiting
Writeriswaiting
onereaderisdone,reading.Count=0\\所有读进程结束,写进程Writer1执行
Writer2iswriting\\写-写互斥,Writer2等待
Itisreader1whohasdonereadingaccordingtocount=0
Writeriswaiting
onewriterisdone,writing.Count=1
ItisWriter2whohasdonewriting.
Writer1iswriting
onewriterisdone,writing.Count=0
ItisWriter1whohasdonewriting.//所有写进程也最后结束
七、总结
通过本次实验,我对读者-写者的过程有了清楚的认识,对互斥和同步有了更深一步的了解,在最开始的实验中,我没有正确理解好写者优先,当有写者等待时,读者就不能进入了,这样就没有实现读读允许,意识到了后,加了个if判断解决了这一问题.在JAVA的线程的使用方法中,释放空间这个方法过去一直用的是notify(),但是由于一直是对单一的线程,这次实验中发现这个方法在这里不可行,所以即时查阅了资料用了notifyall()方法,总的来说,这次是操作系统的第一次实验,感觉最主要的是把脉络理清楚,写代码的工作要比理清脉络简单
课程设计提高了我对所学知识的综合应用能力,全面检查并掌握所学的内容,培养独立思考、刻苦钻研的精神,在分析问题、解决问题的过程中,更是获得一种成功的喜悦,进而增加学习和应用的兴趣。
同时也要督促自己在学习的过程中不断的完善自我,加强自己的动手操作能力,培养我的独立思考的那种思维方式。
课程设计和平时的实验课比较起来有很大的差距,实验课只是将这一章的一部分内容练习操作一遍,而课程设计需要的是他们综合起来的东西,这要更难一些。
总之,每一次课程设计不仅是我们学习的好机会,而且是我们锻炼实际动手能力的平台,虽然有难度的东西总会让人很抵触,比如在课设过程中有很多郁闷的时候,一个小小的错误一不小心就花去了自己一上午的时间,所以在这个过程中能够磨练人的意志与耐心,最后感谢老师的指导与监督。