采用“写优先”的策略演示“读者-写者”问题(C_)_第1页
采用“写优先”的策略演示“读者-写者”问题(C_)_第2页
采用“写优先”的策略演示“读者-写者”问题(C_)_第3页
采用“写优先”的策略演示“读者-写者”问题(C_)_第4页
采用“写优先”的策略演示“读者-写者”问题(C_)_第5页
已阅读5页,还剩16页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、青岛理工大学操作系统课程设计报告院(系): 计算机工程学院 专业: 计算机科学与技术专业 学生姓名: 滕同学 班级:软件102学号: 201007195 题目: 采用“写优先”的策略演示“读者-写者”问题 起迄日期: 2013.7.8-2013.7.17 设计地点: 网络中心计算机学院机房 指 导 教 师: 吴老师 20122013年度 第 2 学期完成日期: 2013 年 7 月 17 日一、 课程设计目的进行操作系统课程设计主要是在学习操作系统课程的基础上,在完成操作系统各部分实验的基础上,对操作系统的整体进行一个模拟,通过实践加深对各个部分的管理功能的认识,还能进一步分析各个部分之间的联

2、系,最后达到对完整系统的理解。同时,可以提高运用操作系统知识解决实际问题的能力;锻炼实际的编程能力、创新能力及团队组织、协作开发软件的能力;还能提高调查研究、查阅技术文献、资料以及编写软件设计文档的能力。此次实验我选择的是经典的读者写者问题。读写者问题的传统解决方案采用读优先策略,可能会造成后续的写者被随后而来的读者插队而长时间等待,直到全部读者进程运行完毕后,才可进行写操作。为此,选择采用“写优先策略”解决读写者问题,希望通过此次课程设计实现利于写者工作的功能,加深对线程、进程及同步概念的理解。通过研究经典的进程同步问题,实现对读者-写者问题的并发控制,掌握运用信号量解决“同类进程多次访问,

3、而不同类的进程必须互斥访问资源”的控制问题。此次实验我选择用比较大众的C#语言编写,因为C#中有semaphore类是对操作系统的semaphore很好的描述。二、 课程设计内容与要求1、设计目的:通过研究经典的进程进步问题,实现对读者-写者问题的并发控制。2、说明:阅览室一次最多可以容纳20个人。3、设计要求:1) 读者与写者至少包括ID、进入内存时间、读写时间三项内容,可在界面上进行输入2) 读者与写者均有二个以上,可在程序运行期间动态增加读者与写者3) 可读取样例数据(要求存放在外部文件中),进行读者/写者、进入内存时间、读写时间的初始化4) 要求将运行过程用可视化界面动态显示,可随时暂

4、停,查看阅览室中读者/写者数目、读者等待队列、写者等待队列、读写时间、等待时间5) 读写策略为:读写互斥、写写互斥、写优先(只要写者到达,就阻塞后续的所有读者,一旦阅览室无人,写者能最快进入阅览室;在写者未出阅读室之前,又有新的读者与写者到达,仍然是写者排在前面)三、 系统分析与设计3.1 系统分析3.1.1 信息分析: 写者优先程序实现写者优先进行写,本程序主要功能包括增加读者写者,时间的显示,动态的显示读写过程,暂停继续。具体实现这些功能所需要的信息表示如下:1) 读者线程信息: public string Id;/读者线程ID public int IncomeTime;/进入内存的时间

5、 public int ServerTime;/需要服务的时间 2)写者线程信息: public string Id;/写者线程ID public int IncomeTime;/进入内存的时间 public int ServerTime;/需要服务的时间 3)计时器线程 (需要的变量) public static DateTime initTime = new DateTime();/开始时系统时间 public static int uptime = 0;/系统暂停的全部时间 public static DateTime pause;/暂停时的时间 public static DateTi

6、me goon;/暂停结束的时间2) 主类中的信息: public static int Rcount = 0;/阅览室内读者的人数 public static int Wcount = 0;/阅览室内写者的人数 public static DataTable rwq = new DataTable();/读者等待队列 public static DataTable wwq = new DataTable();/写者等待队列 public static Label lb1, lb2;/读者写者要访问的控件设置为静态全局变量: /lb1显示 当前是读者,还是写者 /lb2显示当前阅览室的人数3)

7、 信号量信息: public static Semaphore Mut1 = new Semaphore(1, 1);/实现写者优先的信号量 public static Semaphore Mut2 = new Semaphore(1, 1);/访问读者数量的信号量 public static Semaphore Fmutex = new Semaphore(1, 1);/表示浏览室的信号量public static Semaphore rNumber = new Semaphore(20,20);/定义阅览室人数public static Semaphore Pause = new Sema

8、phore(1, 1);/控制访问时间的信号量3.1.2 行为分析:1) 增加读者写者:在文本框中输入进入内存时间,还有服务时间,即可创建读者写者线程,然后直接启动即可,实现动态添加读者写者目的。 2) 外部文本读取:输入文本的名字可读取样例数据(存放在外部文件中),进行读者/ 写者、进入内存时间、读写时间的初始化。 3)时间显示功能:在主函数中点击开始按钮,就启动一个计时线程,并在主界面动态的显示。 4) 数据显示:采用C#中DateGradeView运行过程用可视化界面动态显示,可以随时查看阅览室中读者/写者的等待时间,状态,哪些读者写者处于等待状态。 5) 暂停继续功能:暂停继续的实现,

9、主要是对计时线程的信号量Pause的申请和释放实现的。3.1.2 表示分析: 1)系统主界面设计显示读者写者的运行状态及信息,实现一些功能的按钮。 图 1 主界面设计3.2 系统设计:3.2.1 模块设计:线程开始运行数据初始化主框架窗口数据录入运行过程动态显示单个输入外部文件读取开始运行暂停继续终止 图 3 系统功能模块图 图 4 系统主要流程图3.2.2 数据结构说明:1. 程序中的数据定义: public static int Rcount = 0;/阅览室内读者的人数 public static int Wcount = 0;/阅览室内写者的人数 public static DataT

10、able rwq = new DataTable();/读者等待队列 public static DataTable wwq = new DataTable();/写者等待队列 public static Label lb1, lb2;/读者写者要访问的控件设置为静态全局变量:l /b1显示 当前是读者,还是写者 /lb2显示当前阅览室的人数 public static DateTime initTime = new DateTime();/开始时系统时间 public static int uptime = 0;/系统暂停的全部时间 public static DateTime pause;

11、/暂停时的时间 public static DateTime goon;/暂停结束的时间2. 程序中信号量的定义: public static Semaphore Mut1 = new Semaphore(1, 1);/实现写者优先的信号量 public static Semaphore Mut2 = new Semaphore(1, 1);/访问读者数量的信号量 public static Semaphore Fmutex = new Semaphore(1, 1);/表示浏览室的信号量public static Semaphore rNumber = new Semaphore(20,20

12、);/定义阅览室人数public static Semaphore Pause = new Semaphore(1, 1);/控制访问时间的信号量3.2.3 算法流程图:开始 暂停添加读者,写者继续 读者线程 写者线程 Form1.runTime() < IncomeTimeForm1.runTime() < IncomeTime 是 是等待 否 否Mut1.Wait() Wcount+Mut1.Wait() 是 Mut1.Release() Fmutex.Wait()Wcount>0是 进行写操作 否 Mut2.Wait()Wcount-Rcount+Fmutex.Rele

13、ase()Rcount=1Mut1.Release() 是Fmutex.Wait() 否rNumber.WaitOne()进行读操作rNumber.Release()Mut2.Wait()Rcount-Rcount = 0Fmutex.Release()Mut2.Release()结束四、系统测试与调试分析4.1 系统测试测试技术:单元测试,功能测试。单元测试是从开发者的角度来编写的,检验被测代码中的一个很明确的功能是否正确。通常而言,一个单元测试是用于判断某个特定条件(或者场景)下某个特定函数的行为。例如可以输入正确的用户名和密码以及错误的用户名和密码来确定系统的登陆功能是否正确,如果系统能

14、够处理不同情况的输入则说明此登陆功能没有问题。编写单元测试有助于调用者观察、思考。特别是先写测试,迫使我们把程序设计成易于调用和可测试的,迫使我们解除软件中的耦合。编写单元测试有助于增加程序功能或者更改程序的结构,使程序变得更加完善。功能测试是从使用者的角度来编写的,它关注系统提供的功能特征及其不同的处理条件;测试功能的不同处理流程(包括正常处理的和异常处理),它能帮助开发者更好的发心系统的不足。测试方法:黑盒测试。黑盒测试方法是通过使用整个软件或某种软件功能来严格地测试,而并没有通过检查程序的源代码或者很清楚地了解该软件的源代码程序具体是怎样设计的。测试人员通过输入他们的数据然后看输出的结果

15、从而了解软件怎样工作。在测试时,把程序看作一个不能打开的黑盆子,在完全不考虑程序内部结构和内部特性的情况下,测试者在程序接口进行测试,它只检查程序功能是否按照需求规格说明书的规定正常使用,程序是否能适当地接收和正确的输出。 表 2 文本输入测试测试说明测试名称采用“写优先”的策略演示“读者写者”问题测试目的验证系统对于读者写者多线程的处理流程测试技术单元测试测试方法黑盒测试法测试用例测试内容 读者写者的信息输入测试步骤从界面输入信息从文本中读取输入错误信息测试数据1,R,3,5rw.txt错误的编号预期结果信息显示在table中信息显示在table中出现异常,显示失败测试结果与预期相符与预期相

16、符与预期相符 表 3 读者写者测试 测试说明测试名称采用“写优先”的策略演示“读者写者”问题测试目的验证系统对于读者写者多线程的处理流程测试技术功能测试测试方法黑盒测试法测试用例测试内容在写者后面到达到的读者被阻塞测试步骤把数据从外部文件输入数据库,然后从哈希表中读出开始运行测试数据1 R 1 6 2 R 2 63 W 3 64 W 4 65 R 5 66 R 6 67 W 7 6预期结果1,2 3 4 5,6 7测试结果与预期相符 表 4 读者写者同时到达测试测试说明测试名称采用“写优先”的策略演示“读者写者”问题测试目的验证系统对于读者写者多线程的处理流程测试技术功能测试测试方法黑盒测试法

17、测试用例测试内容读者写者同时到达,写者得到进入阅览室的权利测试步骤从界面添加读者写者的信息,到达时间相同,到数据库然后开始执行测试数据1 R 3 4 2 W 3 4预期结果2 1测试结果与预期相符 表 5 人数测试 测试说明测试名称采用“写优先”的策略演示“读者写者”问题测试目的验证系统对于读者写者多线程的处理流程测试技术功能测试测试方法黑盒测试法测试用例测试内容采用“写优先”的策略演示“读者写者”问题测试步骤从界面添加读者写者的信息,到达时间相同,到哈希表然后开始执行测试数据1 R 4 20 2 R 4 20 3 R 4 20 4 R 4 205 R 4 20 6 R 5 20 7 R 5

18、20 8 R 5 209 R 5 20 10 R 6 20 11 R 6 20 12 R 6 2013 R 6 20 14 R 6 20 15 R 5 20 16 R 5 2017 R 7 20 18 R 7 20 19 R 7 20 20 R 8 2021 R 8 20 22 R 8 20预期结果编号120先执行,21,22阻塞,1-5执行完离开,21,22进入测试结果与预期相符4.2 调试分析:在开始的时候对如何将读者写者问题转化到代码非常疑惑,因为没有没有编写操作系统实验的思想,后来去网上查阅了相关的资料看了一些代码后,才有了一个初步的认识,并看了关于多线程的视频才最终确定用多线程的编写

19、。在整体方面,计算机的时钟是以毫秒来计算的,因此我设计了一个延迟时间Delay=1000,即以1s为一个时钟间隔。在编写过程中遇到了一些问题花费了好多时间才解决。遇到的问题如下:(1) 开始并不知道如何处理到达时间,当其到达时该如何判断并调度它,采用的是循环sleep,每次sleep(1000)一秒。(2) 如何更新运行时间与等待时间。采用timeClock(自己创建的始终线程)对时间进行记录与计算。(3) 进程状态的更新。使用state记录状态,通过申请信号量成功与否来改变状态。(4) 应该创建的线程种类。读者,写者线程,主线程,和timeClock时钟记录线程。五、用户手册5.1 程序开发

20、及运行环境本程序在Win7操作系统下利用图像界面技术设计前台界面,采用C#语言编写后台代码,文件作为后台信息的存储,在vs2010软件上开发。Vs2010下载地址:5.2 具体使用步骤1)打开vs2010软件,点击运行,系统主界面出现。2)选择增加读者写者,出现界面如下图。 主界面显示3) 必须先点击开始,在点击暂停,才能添加读者和写者或者直接点击文件输入,否则出现异常 4) 点击文件输入,即可从文件中读取读者写者信息,然后进行读写操作。 运行信息显示界面5)选择暂停,即可暂停所有线程的运行,然后动态添加读者,写者 6) 点击继续,则可将刚刚添加的读者,还有写者进行读写操作。7) 程序退出选择

21、,点击终止,即可终止程序。六、程序清单6.1 外部文件rw.txt /外部数据录入文件6.2 主要的类 Form.cs /主界面类 Reader.cs /读者类(包含读者信息ID,进入时间,运行时间,以及读者线程调度的read方法。Writer.cs /读者类(包含写者信息ID,进入时间,运行时间,以及写者线程调度的write方法。6.3 本程序的源代码using System;using System.Collections.Generic;using System.ComponentModel;using System.Data;using System.Drawing;using Sys

22、tem.Linq;using System.Text;using System.Windows.Forms;using System.Threading;using System.IO;/* Semaphore的理解通过使用一个计数器对共享资源进行访问控制,Semaphore构造器需要提供初始化的计数器(信号量)大小以及最大的计数器大小访问共享资源时,程序首先申请一个向Semaphore申请一个许可证,Semaphore的许可证计数器相应的减一,当计数器为0时,其他申请该信号量许可证的线程将被堵赛,直到先前已经申请到许可证的线程释放他占用的许可证让计数器加一,这样最近去申请许可证的线程将会得到

23、竞争得到被释放的许可证。常见的操作方法 WaitOne():申请一个许可证 Release():释放占用的许可证 */namespace duzhexiezhe public partial class Form1 : Form public static Semaphore Pause = new Semaphore(1, 1);/控制进程暂停访问时间的信号量 public static Semaphore Mut1 = new Semaphore(1, 1);/实现写者优先的信号量 public static Semaphore Mut2 = new Semaphore(1, 1);/访问

24、读者数量的信号量 public static Semaphore Fmutex = new Semaphore(1, 1);/表示浏览室的信号量 public static Semaphore rNumber = new Semaphore(20,20); public static int Rcount = 0;/阅览室内读者的人数 public static int Wcount = 0;/阅览室内写者的人数 public static DataTable rwq = new DataTable();/读者等待队列 public static DataTable wwq = new Dat

25、aTable();/写者等待队列 public static Label lb1, lb2;/读者写者要访问的控件设置为静态全局变量:lb1显示 当前是读者,还是写者 /lb2显示当前阅览室的人数 public static DateTime initTime = new DateTime();/开始时系统时间 public static int uptime = 0;/系统暂停的全部时间 public static DateTime pause;/暂停时的时间 public static DateTime goon;/暂停结束的时间 public Form1() InitializeComp

26、onent(); private void Form1_Load(object sender, EventArgs e)/初始化一些全局控件 rwq.Columns.Add("进程ID"); rwq.Columns.Add("到达时间"); rwq.Columns.Add("服务时间"); dgvrwq.DataSource = rwq; wwq.Columns.Add("进程ID"); wwq.Columns.Add("到达时间"); wwq.Columns.Add("服务时间&qu

27、ot;); dgvwwq.DataSource = wwq; lb1 = label1; lb2 = label2; public static int time()/开始运行到现在的时间,以秒为单位 TimeSpan d = DateTime.Now.Subtract(initTime); return Convert.ToInt32(d.TotalSeconds); public static int runTime()/程序实际运行的时间 Pause.WaitOne(); Pause.Release(); int t = time() - uptime; return t; public

28、 void timeShow()/显示时间 while (true) Thread.Sleep(20); Pause.WaitOne(); Pause.Release(); lbTime.Text = (time()-uptime).ToString(); private void button3_Click(object sender, EventArgs e)/开始按钮点击事件 initTime = System.DateTime.Now; Thread threadtime = new Thread(timeShow); Control.CheckForIllegalCrossThrea

29、dCalls = false; threadtime.Start(); button3.Enabled = false;/开始按钮 button5.Enabled = false;/导入文件按钮 private void button4_Click(object sender, EventArgs e)/暂停触发的事件 TimeSpan d; if (button4.Text = "暂停")/暂停 Pause.WaitOne(); button4.Text = "继续" pause = DateTime.Now; else /继续 Pause.Relea

30、se(); button4.Text = "暂停" goon = DateTime.Now; d = goon.Subtract(pause); uptime = uptime+Convert.ToInt16(d.TotalSeconds); private void button1_Click(object sender, EventArgs e) Thread t1 = new Thread(newWriter); t1.Start(); public void newWriter()/新写者 Writer w = new Writer(Int32.Parse(text

31、Box1.Text), Int32.Parse(textBox2.Text); textBox1.Text = "" textBox2.Text = "" Thread thread = new Thread(w.write); Control.CheckForIllegalCrossThreadCalls = false; thread.Start(); private void button2_Click(object sender, EventArgs e) Thread thread = new Thread(newReader); thread

32、.Start(); private void newReader()/新读者 Reader r = new Reader(Int32.Parse(textBox3.Text), Int32.Parse(textBox4.Text); textBox3.Text = "" textBox4.Text = "" Thread t = new Thread(r.read); Control.CheckForIllegalCrossThreadCalls = false; t.Start(); private void button5_Click(object

33、sender, EventArgs e)/从文件开始 FileInfo fi = new FileInfo("D:ASP.NETduzhexiezheduzhexiezhedocumentsrw.txt"); /TXT文件路径 StreamReader sr = fi.OpenText(); while(!sr.EndOfStream) string str = sr.ReadLine(); char c = char.Parse(str.Split(' ')0); int t1 = int.Parse(str.Split(' ')1); i

34、nt t2 = int.Parse(str.Split(' ')2); if (c.Equals('r') Reader r = new Reader(t1, t2); Thread t = new Thread(r.read); Control.CheckForIllegalCrossThreadCalls = false; t.Start(); if (c.Equals('w') Writer w = new Writer(t1,t2); Thread t = new Thread(w.write); Control.CheckForIlle

35、galCrossThreadCalls = false; t.Start(); initTime = System.DateTime.Now; Thread threadtime = new Thread(timeShow); Control.CheckForIllegalCrossThreadCalls = false; threadtime.Start(); button3.Enabled = false; button5.Enabled = false; private void Form_Close(object sender, FormClosingEventArgs e) Envi

36、ronment.Exit(0); Application.Exit(); private void button6_Click(object sender, EventArgs e)/终止 this.Close(); public class Reader/读者类 public string Id; public int IncomeTime; public int ServerTime; public Reader(int ctime,int stime) IncomeTime = ctime; ServerTime = stime; public void read() DataRow d

37、r; dr = Form1.rwq.NewRow(); dr"进程ID" = Thread.CurrentThread.ManagedThreadId; dr"到达时间" = IncomeTime; dr"服务时间" = ServerTime; Form1.rwq.Rows.Add(dr); while (Form1.runTime() < IncomeTime) Form1.Pause.WaitOne(); Form1.Pause.Release(); /下面if代码保证了写者优先 Form1.Mut1.WaitOne();

38、/读者需要先申请Mut1,如果有写者在等待Fmutex,则读者被阻塞,写者优先 Form1.Mut1.Release(); /立即释放Mut1,使写者可以随时申请到Mut1 /不断测试有没有写者 while(Form1.Wcount>0) /Thread.Sleep(100); Form1.Mut2.WaitOne(); Form1.Rcount = Form1.Rcount + 1; if (Form1.Rcount = 1) Form1.Fmutex.WaitOne(); /第一个读者进入时,申请Fmutex;如有写者,第一个读者会阻塞在此处 Form1.Mut2.Release()

39、; Form1.rNumber.WaitOne();/图书室没座位则阻塞 /读操作; Form1.lb1.Text = "读者" Form1.lb2.Text = Form1.Rcount.ToString();/显示读者数 Form1.lb2.Update(); DateTime dt1 = DateTime.Now; TimeSpan ts=DateTime.Now.Subtract(dt1); while (ts.TotalSeconds < ServerTime) ts = DateTime.Now.Subtract(dt1); Form1.Pause.Wai

40、tOne(); Form1.Pause.Release(); Form1.rwq.Rows.Remove(dr); Form1.rNumber.Release();/读者释放座位 Form1.Mut2.WaitOne(); Form1.Rcount = Form1.Rcount - 1; if (Form1.Rcount = 0) Form1.Fmutex.Release(); /最后一个读者退出时,释放Fmutex Form1.lb2.Text = Form1.Rcount.ToString();/显示读者数 Form1.Mut2.Release(); public class Writer/写者类 public string Id; public int IncomeTime; public int ServerTime; public Writer(int ctime, int stime) IncomeTime = ctime; ServerTime = stime; public void write() DataRow dr;/数据表的一行 dr = Form1.wwq.NewRow(); dr"进程ID" = T

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论