
实验序号:操作系统实验(二) 实验项目名称:读者写者问题
| 学 号 | 姓 名 | 队别 | ||||
| 实验地点 | 指导教员 | 实验时间 | ||||
| 一、实验目的及要求 实验目的:综合运用多进程并发控制,进程同步互斥,信号量机制等原理解决问题。 实验要求:本题目安排16学时,要求党员根据题目要求,写出算法,在VC平台上进行程序设计和调试,在运行成功的基础上,整理出源程序和运行结果.写出设计报告。 二、实验设备(环境) 实验设备: WINDOWS 2000环境、VC平台、WIN 32 API 三、实验内容与步骤 实验内容与步骤:可以将所有读者和写者分别存于一个读者等待队列和一个写者等待队列,每当读允许时,就从读者队列中释放一个或多个读者线程进行读操作;每当写允许时,就从写者队列中释放一个写者进行写操作. a)读者优先 读者优先指的是除非有写者在写文件,否则读者不需要等待.所以可以用一个整形变量记录当前读者的数目,用于确定是否需要释放正在等待的写者线程.每一个读者开始读文件时,必须修改变量.因此需要一个互斥对象mutex来实现对全局变量修改时的互斥. 另外,为了实现写互斥,需要增加一个临界区对象 write.当写者发出写请求时,必须申请临界区对象的所有权.通过这种方法,也可以实现读写互斥,当read_count=1时,读者线程也必须申请临界区对象的所有权. 当读者拥有临界区所有权时,写者阻塞在临界区对象write上.当写者拥有临界区所有权时,第一个读者判断完”read_count==1”后阻塞在write上,其余的读者由于等待对read_count的判断,阻塞在mutex上. b)写者优先 写者优先与读者优先类似.不同之处在于一旦一个写者到来,它应该尽快对文件进行写操作,如果有一个写者在等待,则新到来的读者不允许进行读操作.为此应当添加一个整形变量write_count,用于记录正在等待的写者的数目,当write_count=0时,才可以释放等待的读者线程队列. 为了对全局变量write_count实现互斥,必须增加一个对象mutex3. 为了实现写者优先,应当添加一个临界区对象read,当有写者在写文件或等待时,读者必须阻塞在read上. 读者线程除了要对全局变量read_count实现操作上的互斥外,还必须有一个互斥对象对阻塞read这一过程实现互斥.这两个互斥对象分别命名为mutex1和mutex2。 四、实验结果与数据处理 源代码 #include #include #include #include #include #include #define MAX_PERSON 100 #define READER 0 //读者 #define WRITER 1 //写者 #define END -1 #define R READER #define W WRITER typedef struct _Person { HANDLE m_hThread;//定义处理线程的句柄 int m_nType;//进程类型(读写) int m_nStartTime;//开始时间 int m_nWorkTime;//运行时间 int m_nID;//进程号 }Person; Person g_Persons[MAX_PERSON]; int g_NumPerson = 0; long g_CurrentTime= 0;//基本时间片数 int g_PersonLists[] = {//进程队列 1, W, 4, 5, 2, W, 16, 4, 3, R, 5, 2, 4, W, 6, 5, 5, R, 4, 3, END, }; int g_NumOfReading = 0; int g_NumOfWriteRequest = 0;//申请写进程的个数 HANDLE g_hReadSemaphore;//读者信号 HANDLE g_hWriteSemaphore;//写者信号 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() { g_hReadSemaphore = CreateSemaphore(NULL,1,100,NULL); //创建信号灯,当前可用的资源数为,最大为 g_hWriteSemaphore = CreateSemaphore(NULL,1,100,NULL); //创建信号灯,当前可用的资源数为,最大为 CreatePersonList(g_PersonLists); // Create All the reader and writers printf("Created all the reader and writer\\n...\\n"); g_CurrentTime = 0; while(true) { g_CurrentTime++; Sleep(300); // 300 ms printf("CurrentTime = %d\\n",g_CurrentTime); if(finished) return 0; system ("pause"); } // return 0; } void CreatePersonList(int *pPersonLists) { int i=0; int *pList = pPersonLists; bool Ret; while(pList[0] != END) { switch(pList[1]) { case R: Ret = CreateReader(pList[2],pList[3],pList[0]);//351,w452,523,654 break; case W: Ret = CreateWriter(pList[2],pList[3],pList[0]); break; } if(!Ret) printf("Create Person %d is wrong\\n",pList[0]); pList += 4; // move to next person list } } DWORD WINAPI ReaderProc(LPVOID lpParam)//读过程 { Person *pPerson = (Person*)lpParam; // wait for the start time while(g_CurrentTime != pPerson->m_nStartTime) { } printf("Reader %d is Requesting ...\\n",pPerson->m_nID); printf("\\n\\n************************************************\\n"); // wait for the write request WaitForSingleObject(g_hReadSemaphore,INFINITE); if(g_NumOfReading ==0) { WaitForSingleObject(g_hWriteSemaphore,INFINITE); } g_NumOfReading++; ReleaseSemaphore(g_hReadSemaphore,1,NULL); pPerson->m_nStartTime = g_CurrentTime; printf("Reader %d is Reading the Shared Buffer...\\n",pPerson->m_nID); printf("\\n\\n************************************************\\n"); while(g_CurrentTime <= pPerson->m_nStartTime + pPerson->m_nWorkTime) {} printf("Reader %d is Exit...\\n",pPerson->m_nID); printf("\\n\\n************************************************\\n"); WaitForSingleObject(g_hReadSemaphore,INFINITE); g_NumOfReading--; if(g_NumOfReading == 0) {ReleaseSemaphore(g_hWriteSemaphore,1,NULL);//此时没有读者,可以写 } ReleaseSemaphore(g_hReadSemaphore,1,NULL); if(pPerson->m_nID == 4) finished = true; //所有的读写完成 ExitThread(0); return 0; } DWORD WINAPI WriterProc(LPVOID lpParam) { Person *pPerson = (Person*)lpParam; // wait for the start time while(g_CurrentTime != pPerson->m_nStartTime) {} printf("Writer %d is Requesting ...\\n",pPerson->m_nID); printf("\\n\\n************************************************\\n"); WaitForSingleObject(g_hWriteSemaphore,INFINITE); // modify the writer's real start time pPerson->m_nStartTime = g_CurrentTime; printf("Writer %d is Writting the Shared Buffer...\\n",pPerson->m_nID); while(g_CurrentTime <= pPerson->m_nStartTime + pPerson->m_nWorkTime) {} printf("Writer %d is Exit...\\n",pPerson->m_nID); printf("\\n\\n************************************************\\n"); //g_NumOfWriteRequest--; ReleaseSemaphore(g_hWriteSemaphore,1,NULL); if(pPerson->m_nID == 4) finished = true;//所有的读写完成 ExitThread(0); return 0; } bool CreateReader(int StartTime,int WorkTime,int ID) { DWORD dwThreadID; if(g_NumPerson >= MAX_PERSON) return false; Person *pPerson = &g_Persons[g_NumPerson]; pPerson->m_nID = ID; pPerson->m_nStartTime = StartTime; pPerson->m_nWorkTime = WorkTime; pPerson->m_nType = READER; g_NumPerson++; // Create an New Thread pPerson->m_hThread= CreateThread(NULL,0,ReaderProc,(LPVOID)pPerson,0,&dwThreadID); if(pPerson->m_hThread == NULL) return false; return true; } bool CreateWriter(int StartTime,int WorkTime,int ID) { DWORD dwThreadID; if(g_NumPerson >= MAX_PERSON) return false; Person *pPerson = &g_Persons[g_NumPerson]; pPerson->m_nID = ID; pPerson->m_nStartTime = StartTime; pPerson->m_nWorkTime = WorkTime; pPerson->m_nType = WRITER; g_NumPerson++; // Create an New Thread pPerson->m_hThread= CreateThread(NULL,0,WriterProc,(LPVOID)pPerson,0,&dwThreadID); if(pPerson->m_hThread == NULL) return false; return true; } 五、分析与讨论 通过这次课程设计,让我对课本上的理论知识有了更深刻的认识,通过自己的动手实践,把理论知识真正的化为了自己可以应用的技能.在这次实验中 也遇到了不少困难,往往一个小小的错误,就会导致整个程序不能正常运行,寻找错误、发现错误和修改错误,每一次改进都需要花费大量的时间和精力,每取得一次小的成功都离最后的成功更近了一步,每一次改正也会带来巨大的欣喜,这正是一个进步和提高的过程.在这个过程中获得了很多收获. | ||||||
| 六、教员评语 签名: 日期: | 成绩 | |||||
