当前位置:文档之家› 操作系统课程设计读者写者问题

操作系统课程设计读者写者问题

计算机与信息学院操作系统课程设计报告一、开题报告(一)该项课程设计的意义;1.更加深入的了解读者写者问题的算法;2.加深对线程,进程的理解;3.加深对“线程同步”概念的理解,理解并应用“信号量机制”;4.熟悉计算机对处理机的管理,了解临界资源的访问方式;5.了解C++中线程的实现方式,研读API。

(二)课程设计的任务多进程/线程编程:读者-写者问题。

●设置两类进程/线程,一类为读者,一类为写者;●随机启动读者或写者;●显示读者或写者执行状态;●随着进程/线程的执行,更新显示;(三)相关原理及算法描述;整体概况:该程序从大体上来分只有两个模块,即“读者优先”和“写者优先”模块.读者优先:如果没有写者正在操作,则读者不需要等待,用一个整型变量readcount记录读者数目,用于确定是否释放读者线程,readcount的初值为0.当线程开始调入时.每个读者准备读. 等待互斥信号,保证对readcount 的访问,修改互斥.即readcount++.而当读者线程进行读操作时,则读者数目减少(readcount--).当readcout=0 时,说明所有的读者都已经读完,离开临界区唤醒写者(LeaveCriticalSection(&RP_Write);), 释放互斥信号(ReleaseMutex(h_Mutex)).还需要一个互斥对象mutex来实现对全局变量Read_count修改时的互斥. 另外,为了实现写-写互斥,需要增加一个临界区对象Write。

当写者发出写请求时,必须申请临界区对象的所有权。

通过这种方法,可以实现读-写互斥,当Read_count=1时(即第一个读者到来时),读者线程也必须申请临界区对象的所有权写者优先:写者优先与读者不同之处在于一旦一个写者到来,它应该尽快对文件进行写操作,如果有一个写者在等待,则新到来的读者不允许进行读操作。

为此应当填加一个整形变量write_count,用于记录正在等待的写者的数目,write_count的初值为0.当线程开始调入时.只允许一个写者准备读. 等待互斥信号,保证对write_count 的访问,修改互斥.即write_count++.而当写者线程进行读操作时,则相应写者数目减少(write_count--).当write_count=0 时,说明所有的读者都已经读完,离开临界区唤醒读者,释放互斥信号.为了实现写者优先,应当填加一个临界区对象read,当有写者在写文件或等待时,读者必须阻塞在read上。

(四)开发环境;VC++6.0(五)预期设计目标;读者-写者问题的读写操作限制(包括读者优先和写者优先)1.写-写互斥:不能有两个写者同时进行写操作2.读-写互斥:不能同时有一个线程在读,而另一个线程在写。

3.读-读允许:可以有一个或多个读者在读。

若读者的优先权比写者高, 如果读者申请进行读操作时已有另一个读者正在进行读操作,则该读者可直接开始读操作.不必经过别的操件若读者的优先权比写者高,如果第一个写者已经占有了文件的时候.则别的读者必需等待该操作完成后.才能开始读操作.若写者的优先权比读者高, 在一个写者提出要访问文件时,就必须使其尽可能的得到文件,而且不用调配。

完成课程设计的任务,实现读者写者问题的全部要求,同时可以实现“读者优先”和“写者优先”两种情况,有时间的话,争取实现可视化图形界面。

二、课程设计报告(一)课程设计任务、要求、目的;任务和要求:多进程/线程编程:读者-写者问题。

●设置两类进程/线程,一类为读者,一类为写者;●随机启动读者或写者;●显示读者或写者执行状态;●随着进程/线程的执行,更新显示;目的:1 更加深入的了解读者写者问题的算法;2 加深对线程,进程的理解;3 加深对“线程同步”概念的理解,理解并应用“信号量机制”;4 熟悉计算机对处理机的管理,了解临界资源的访问方式;5 了解C++中线程的实现方式,研读API。

(二)原理及算法描述;写者优先原理图:读者优先原理图:算法描述:读者优先的附加限制:如果读者申请进行读操作时已有另一个读者正在进行读操作,则该读者可直接开始读操作。

写者优先的附加限制:如果一个读者申请进行读操作时已有另一个写者在等待访问共享资源,则该读者必须等到没有写者处于等待状态后才能开始读操作。

(三)开发环境;VC++6.0(四)重要算法和设计思路描述;整体概况:该程序从大体上来分只有两个模块,即“读者优先”和“写者优先”模块.读者优先:如果没有写者正在操作,则读者不需要等待,用一个整型变量readcount记录读者数目,用于确定是否释放读者线程,readcount的初值为0.当线程开始调入时.每个读者准备读. 等待互斥信号,保证对readcount 的访问,修改互斥.即readcount++.而当读者线程进行读操作时,则读者数目减少(readcount--).当readcout=0 时,说明所有的读者都已经读完,离开临界区唤醒写者(LeaveCriticalSection(&RP_Write);), 释放互斥信号(ReleaseMutex(h_Mutex)).还需要一个互斥对象mutex来实现对全局变量Read_count修改时的互斥. 另外,为了实现写-写互斥,需要增加一个临界区对象Write。

当写者发出写请求时,必须申请临界区对象的所有权。

通过这种方法,可以实现读-写互斥,当Read_count=1时(即第一个读者到来时),读者线程也必须申请临界区对象的所有权写者优先:写者优先与读者不同之处在于一旦一个写者到来,它应该尽快对文件进行写操作,如果有一个写者在等待,则新到来的读者不允许进行读操作。

为此应当填加一个整形变量write_count,用于记录正在等待的写者的数目,write_count的初值为0.当线程开始调入时.只允许一个写者准备读. 等待互斥信号,保证对write_count 的访问,修改互斥.即write_count++.而当写者线程进行读操作时,则相应写者数目减少(write_count--).当write_count=0 时,说明所有的读者都已经读完,离开临界区唤醒读者,释放互斥信号.为了实现写者优先,应当填加一个临界区对象read,当有写者在写文件或等待时,读者必须阻塞在read上。

(五)程序实现---数据结构;相关WindowsAPI说明:CreateThread: 创建一个在调用进程的地址空间中执行的线程。

ExitThreadSleep: 对指定的时间间隔挂起当前的执行线程CreateMutex: 创建有名或者无名的互斥对象ReleaseMutex:WaitForSingleObject: 当发生(1)指定对象处于信号态(2)超时则该函数返回WaitForMultipleObject: 任意一个或全部指定对象处于信号态或超时间隔已过时,返回CreateSemapore: 创建一个有名或无名信号对象。

ReleaseSemapore:InitializeCriticalSection: 初始化临界区对象EnterCriticalSection: 等待指定临界区对象的所有权。

当调用线程被赋予所有权时,返回。

LeaveCriticalSection:该函数释放指定临界区对象的所有权。

(六)程序实现---程序清单;#include <windows.h>//#include <ctype.h>//#include <stdio.h>//#include <string.h>//#include <stdlib.h>//#include <malloc.h>#include<iostream>using namespace std;#define MAX_PERSON 100 //最多100人#define READER 0 //读者#define WRITER 1 //写者#define END -1 //结束//#define R READER//#define W WRITERtypedef struct{HANDLE m_hThread;//定义处理线程的句柄int Type;//进程类型(读写)int StartTime;//开始时间int WorkTime;//运行时间int ID;//进程号}Person;Person Persons[MAX_PERSON];int NumOfPerson = 0;long CurrentTime= 0;//基本时间片数int PersonLists[] = {//进程队列1, WRITER, 3, 5,2, WRITER, 16, 5,3, READER, 2, 2,4, WRITER, 6, 5,5, READER, 4, 3,6, READER, 17,7,END,};int NumOfReading = 0;int NumOfWriteRequest = 0;//申请写进程的个数HANDLE ReadSemaphore;//读者信号HANDLE WriteSemaphore;//写者信号bool finished = false; //所有的读完成//bool wfinished = false; //所有的写完成void CreatePersonList(int *pPersonList);bool CreateReader(int StartTime,int WorkTime,int ID);bool CreateWriter(int StartTime,int WorkTime,int ID);DWORD WINAPI ReaderProc(LPVOID lpParam);DWORD WINAPI WriterProc(LPVOID lpParam);int main(){ReadSemaphore = CreateSemaphore(NULL,1,100,NULL);//创建信号量,当前可用的资源数为1,最大为100/*HANDLE CreateSemaphore(LPSECURITY_ATTRIBUTES lpSemaphoreAttributes, //lpSemaphoreAttributes为安全属性LONG lInitialCount, //lInitialCount为Semaphore的初始值LONG lMaximumCount, //lMaximumCount为最大值LPCTSTR lpName //lpName为Semaphore对象的名字,NULL表示创建匿名Semaphore);*/WriteSemaphore = CreateSemaphore(NULL,1,100,NULL); //创建信号量,当前可用的资源数为1,最大为100CreatePersonList(PersonLists); // 创建所有读者写者cout<<"创建所有的读者写者"<<"\n...\n";CurrentTime = 0;while(true){CurrentTime++;Sleep(300); // 300 mscout<<"当前时间= "<<CurrentTime<<endl;if(finished) return 0;}// return 0;}void CreatePersonList(int *pPersonLists){int i=0;int *pList = pPersonLists;bool Ret;while(pList[0] != END){switch(pList[1]){case READER:Ret = CreateReader(pList[2],pList[3],pList[0]);break;case WRITER:Ret = CreateWriter(pList[2],pList[3],pList[0]);break;}if(!Ret)printf("Create Person %d is wrong\n",pList[0]);pList += 4; // 寻找下一个读者或者写者}}bool CreateReader(int StartTime,int WorkTime,int ID){DWORD dwThreadID;if(NumOfPerson >= MAX_PERSON)return false;Person *pPerson = &Persons[NumOfPerson];pPerson->ID = ID;pPerson->StartTime = StartTime;pPerson->WorkTime = WorkTime;pPerson->Type = READER;NumOfPerson++;// 新建进程pPerson->m_hThread= CreateThread(NULL,0,ReaderProc,(LPVOID)pPerson,0,&dwThreadID);/*HANDLE CreateThread(LPSECURITY_ATTRIBUTES lpThreadAttributes, // pointer to security attributes 安全属性DWORD dwStackSize, // initial thread stack size 堆栈大小LPTHREAD_START_ROUTINE lpStartAddress, // pointer to thread function 函数指针LPVOID lpParameter, // argument for new threadDWORD dwCreationFlags, // creation flagsLPDWORD lpThreadId // pointer to receive thread ID);*/if(pPerson->m_hThread == NULL)return false;return true;}bool CreateWriter(int StartTime,int WorkTime,int ID){DWORD dwThreadID;if(NumOfPerson >= MAX_PERSON)return false;Person *pPerson = &Persons[NumOfPerson];pPerson->ID = ID;pPerson->StartTime = StartTime;pPerson->WorkTime = WorkTime;pPerson->Type = WRITER;NumOfPerson++;// 新建进程pPerson->m_hThread= CreateThread(NULL,0,WriterProc,(LPVOID)pPerson,0,&dwThreadID);/*HANDLE CreateThread(LPSECURITY_ATTRIBUTES lpThreadAttributes, // pointer to security attributes 安全属性DWORD dwStackSize, // initial thread stack size 堆栈大小LPTHREAD_START_ROUTINE lpStartAddress, // pointer to thread function 函数指针LPVOID lpParameter, // argument for new threadDWORD dwCreationFlags, // creation flagsLPDWORD lpThreadId // pointer to receive thread ID);*/if(pPerson->m_hThread == NULL)return false;return true;}DWORD WINAPI ReaderProc(LPVOID lpParam)//读过程{Person *pPerson = (Person *)lpParam;// 等待启动时间while(CurrentTime != pPerson->StartTime){//读操作还没有到达执行时间,则等待printf("Reader %d is Requesting ...\n",pPerson->ID);printf("\n\n************************************************\n");//等待写者请求//该语句在写者优先的时候是认为写者优先级高于读者,在有写者的时候读者需要等候,而在读者优先的时候,不用判断是否存在写者,有读者时即开始读操作。

相关主题