当前位置:文档之家› 操作系统OS报告读者与写者问题(进程同步问题)

操作系统OS报告读者与写者问题(进程同步问题)

操作系统OS报告读者与写者问题(进程同步问题) 沈阳理工大学课程设计专用纸 No1目录一、课程设计目的及要求 ................................ 1 二、相关知识 .......................................... 1 三、题目分析 .......................................... 2 四、概要设计 .......................................... 4 五、代码及流程 ........................................ 5 六、运行结果 ......................................... 11 七、设计心得 ......................................... 12 八、参考文献 (12)1沈阳理工大学课程设计专用纸 No1一、课程设计目的及要求读者与写者问题(进程同步问题)用n 个线程来表示n个读者或写者。

每个线程按相应测试数据文件的要求,进行读写操作。

请用信号量机制分别实现读者优先和写者优先的读者-写者问题。

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

二、相关知识Windows API:在本实验中涉及的API 有:1线程控制:CreateThread 完成线程创建,在调用进程的地址空间上创建一个线程,以执行指定的函数;它的返回值为所创建线程的句柄。

HANDLE CreateThread(LPSECURITY_ATTRIBUTES lpThreadAttributes, // SDDWORD dwStackSize, // initial stack sizeLPTHREAD_START_ROUTINE lpStartAddress, // threadfunctionLPVOID lpParameter, // thread argumentDWORD dwCreationFlags, // creation optionLPDWORD lpThreadId // thread identifier);2 ExitThread 用于结束当前线程。

VOID ExitThread(DWORD dwExitCode // exit code for this thread);3 Sleep 可在指定的时间内挂起当前线程。

VOID Sleep(DWORD dwMilliseconds // sleep time);4信号量控制:WaitForSingleObject 可在指定的时间内等待指定对象为可用状态;DWORD WaitForSingleObject(HANDLE hHandle, // handle to objectDWORD dwMilliseconds // time-out interval);1沈阳理工大学课程设计专用纸 No1hHandle为等待的对象,也就是实现同步或者互斥的对象。

该函数一执行,相应的信号量就减去1,如果信号量小于等于0,那么他一直在循环。

5 实现信号量互斥和同步CreateSemaphore用于创建信号量,根据参数的不同可以利用它实现互斥和同步。

ReleaseSemaphore用于释放信号量,使用后相应的信号量加1HANDLE CreateSemaphore(LPSECURITY_ATTRIBUTES lpSemaphoreAttributes,//SDLONG,lInitialCount, //initial countLONG,lMaximumCount, //maximum countLPCTSTR lpName //object name);ReleaseSemaphore(HANDLE hSemaphore, //handle to semaphoreLONG lRelseaseCount, //cont increment amountLPLONG lpPreviousCount //previous count);三、题目分析将所有的读者和所有的写者分别放进两个等待队列中,当读允许时就让读者队列释放一个或多个读者,当写允许时,释放第一个写者操作。

(1)构筑读者进程和写者进程间的临界区题目中说的一批数据被多个读者、写者共享使用,允许多个读者同时访问这些数据,但是如果有一个写者在访问数据时,就不允许其他读者或写者使用,所以,对这一批数据既要保证读者和写者互斥使用,也要保证写者与写者互斥使用。

也就是说,在读者进程程序中,使用数据的程序段应该构成临界区;在写者进程程序中,使用数据的程序段应该构成临界区。

(2)判定是否是第一个读者根据上面的分析,希望在读者进程中有一个办法能判定请求进入临界区的是否是第一个读者。

如果是第一个读者,就对信号量wsem做P操作,以取得和写者的同步。

为此,设置一个变量rfirst,初值为0.任何一个读者运行时,都现在rfirst上加1,然后判定他是否取值为1.如果是1,则做P(wrt),否则不做。

(3)判定是否是第一个写者原理同(2)判定是否为第一个读者。

(4)写者优先问题的解决需要用到的如下的信号量和变量rsem: 初值为1的互斥信号量,在至少有一个写者准备访问数据时就不允许随后来的读者访问数据wserm: 初值为1的互斥信号量,之后有一个写者访问数据时其他写者和读者就被阻止对数据的访问ReadMutex: 创建写者的互斥信号量,初值为1WriteMutex: 创建读者的互斥信号量,初值为1z: 初值为1的互斥信号量,在至少有一个写着准备访问数据、且后面已经来一个读者时再来的读者将在这个信号量上等待2沈阳理工大学课程设计专用纸 No1 rifrrst:读者计数变量,初值为0wfirst:写者计数变量,初值为0写者优先的PV原语:reader(i): Writer():{ {P(z); P(WriteMutex);P(rsem); wfirst=wfirst+1;P(ReadMutex); if(wfirst==1)rfirst=rfirst+1; P(rsem);if(rfirst==1) V(WritedMutex);P(wsem); P(wsem);V(ReadMutex); 改写所需数据;V(rsem); V(wsem);V(z); P(WriteMutex);读取所需数据; wfirst=wfirst-1;P(ReadMutex); if(wfirst==0)rfirst=rfirst-1; V(rsem);if(rfirst==0) V(WriteMutex);V(wsem); }V(ReadMutex);}读者写者图3.1读者-写者的完整流程框图3沈阳理工大学课程设计专用纸 No1 (5)读者优先与写者优先算法相反,有一个读者优先的算法,即只要有读者在读数据,写者被拒绝在临界区外面,如果有源源不断的写者来,但是只要写者不是第一个,那么写者将会永远被拒绝在临界区外面。

wrt::初值为1的互斥信号量,只要有一个写者访问数据,则其他写者和读者就要被阻止对数据的访问。

mutex:保证读者互斥操作first的信号量,初值为1first :读者计数变量,初值为0读者优先的PV原语:read():{P(mutex);first = first+1; write(): if(first == 1) { P(wrt);P(wrt); V(mutex);对数据进行修改; 读取所需数据V(wrt); P(mutex); } first = first+1;if(first == 0)V(wrt);V(mutex);}四、概要设计(1)控制流程用CheckPersonList(PersonLists)函数检查PersonLists中是否有为创建的进程(读写者)。

如果有则创建相应的读写线程(2)创建读写者用bool CreateReader(int StartTime,int WorkTime)函数创建读者写者相应的线程,其中由windows提供的函数为CreateThread(NULL,0,ReaderProc,(LPVOID)pPerson,0,&dwThreadID);返回的是DWORD型变量。

在CreateReader(int StartTime,int WorkTime)中还会初始化相应的读写者的基本信息,例如何时申请数据何时读数据何时关闭线程等等。

(3)读写者进程参见图2.1读者-写者的完整流程图。

(4)同步与互斥WaitForSingleObject(信号量名字,infinite)和ReleaseSemaphore(信号量名字,1,null)用于实现同步于互斥,执行WaitForSingleObject(信号量名字,infinite)信号量相应的信号量减1,执行ReleaseSemaphore(信号量名字,1,null)恢复1。

4沈阳理工大学课程设计专用纸 No1五、代码及流程//写者优先算法#include <windows.h> #include <ctype.h>#include <stdio.h>#include <string.h>#include <stdlib.h> #include <malloc.h>#define MAX_PERSON 10 #define READER 01 #define WRITER #define END -1 #define R READER #define W WRITERtypedef struct _Person {HANDLE Thread;int Type;int StartTime;int WorkTime;int ID;}Person;Person Persons[MAX_PERSON]; int NumPerson = 0; long CurrentTime= 0;int PersonLists[] = {1,R,1,3,2,W,2,5,/*读写互斥*/3,W,5,5,/*写写互斥*/4,R,3,5,/*写读互斥*/5,R,15,2,/*读读不互斥*/END,};int rfirst = 0;int wfirst = 0;int NumOfReaders = 0; int NumOfWriters = 0;5沈阳理工大学课程设计专用纸 No1 HANDLE rsem;/*初值为1的互斥信号量,在至少有一个写者准备访问数据时就不允许随后来的读者访问数据*/HANDLE wsem;/*初值为1的互斥信号量,之后有一个写者访问数据时其他写者和读者就被阻止对数据的访问*/HANDLE z;/*初值为1的互斥信号量,在至少有一个写着准备访问数据、且后面已经来一个读者时再来的读者将在这个信号量上等待*/HANDLE ReadMutex;/*创建写者的互斥信号量,初值为1*/HANDLE WriteMutex;/*创建读者的互斥信号量, 初值为1*/void CheckPersonList(int *pPersonList);/*查看人数,为创建读写者线程*/ bool CreateReader(int StartTime,int WorkTime);bool CreateWriter(int StartTime,int WorkTime);DWORD WINAPI ReaderProc(LPVOID lpParam);/*读者进程程序*/ DWORD WINAPI WriterProc(LPVOID lpParam);/*写着进程程序*/#include "Writerprior.h"int main(){rsem = CreateSemaphore(NULL,1,1,NULL);wsem = CreateSemaphore(NULL,1,1,NULL);z = CreateSemaphore(NULL,1,1,NULL);ReadMutex = CreateSemaphore(NULL,1,1,NULL);WriteMutex = CreateSemaphore(NULL,1,1,NULL);CurrentTime = 0;while(true)//模拟20个时钟周期{CheckPersonList(PersonLists);CurrentTime++;Sleep(600);printf("当前时间 = %d:\n",CurrentTime); if(CurrentTime==20)break;}system("pause");CloseHandle(rsem);CloseHandle(wsem);CloseHandle(z);CloseHandle(ReadMutex);CloseHandle(WriteMutex);return 0;6沈阳理工大学课程设计专用纸 No1 }void CheckPersonList(int *pPersonLists) { int i=0;int *pList = pPersonLists;bool P;while(pList[0] != END){if(pList[2] == CurrentTime){switch(pList[1]){case R:P = CreateReader(pList[2],pList[3]);//创建一个读者break;case W:P = CreateWriter(pList[2],pList[3]);//创建一个写者break;}if(!P)printf("Create Person %d is wrong\n",pList[0]);}pList += 4; // 数组的指针指向第二个人}}DWORD WINAPI ReaderProc(LPVOID lpParam) {Person *pPerson = (Person*)lpParam;pPerson->ID = ++NumOfReaders;WaitForSingleObject(z,INFINITE);//P(z),其余读者在此排队printf("\t\t读者 %d 申请读数据...\n",pPerson->ID);WaitForSingleObject(rsem,INFINITE);//P(rsem),一个读者与一个写着再次竞争数据的使用权//printf("Reader %d is requesting the Shared Buffer...\n",pPerson->ID);WaitForSingleObject(ReadMutex,INFINITE);//P(ReadMutex),读者请求进入rfirst临界区rfirst++;if(rfirst == 1)//是否是第一个读者7沈阳理工大学课程设计专用纸 No1{WaitForSingleObject(wsem,INFINITE);//读者在此处与写者进行同步}ReleaseSemaphore(ReadMutex,1,NULL);//退出rfirst临界区,V(ReadMutex) ReleaseSemaphore(rsem,1,NULL);ReleaseSemaphore(z,1,NULL);//V(z)// 读取所需数据,将现在时间赋值给读者,用以计算结束时间printf("\t\t读者 %d 申请成功\n",pPerson->ID);pPerson->StartTime = CurrentTime;printf("\t\t读者 %d 正在读数据...\n",pPerson->ID);while(CurrentTime < pPerson->StartTime + pPerson->WorkTime){// 模拟读数据}printf("\t\t读者 %d 读完数据退出\n",pPerson->ID); WaitForSingleObject(ReadMutex,INFINITE);rfirst--;if(rfirst == 0) //是最后一个读者,ReleaseSemaphore(wsem,1,NULL);//没有读者了,写者放行ReleaseSemaphore(ReadMutex,1,NULL);//退出读者临界区ExitThread(0);//关闭读者线程return 0;}DWORD WINAPI WriterProc(LPVOID lpParam)//写者进程程序{Person *pPerson = (Person*)lpParam;pPerson->ID = ++NumOfWriters;printf("\t\t写者 %d 正在申请写数据...\n",pPerson->ID); WaitForSingleObject(WriteMutex,INFINITE);//请求进入写者临界区wfirst=wfirst++;if(wfirst==1){WaitForSingleObject(rsem,INFINITE);//一个写者在此与读者取得同步}ReleaseSemaphore(WriteMutex,1,NULL);//退出rfirst临界区8沈阳理工大学课程设计专用纸 No1WaitForSingleObject(wsem,INFINITE);//其他写者在此等候进入写临界区// 读取所需数据,将现在时间赋值给读者,用以计算结束时间pPerson->StartTime = CurrentTime;printf("\t\t写者 %d 正在写数据...\n",pPerson->ID);while(CurrentTime < pPerson->StartTime + pPerson->WorkTime) {//模拟写数据}printf("\t\t写者 %d 写完数据退出\n",pPerson->ID);ReleaseSemaphore(wsem,1,NULL);//退出进入写临界区WaitForSingleObject(WriteMutex,INFINITE);//请求进入wfirst临界区wfirst=wfirst--;if(wfirst==0)//是最后一个写者,{ReleaseSemaphore(rsem,1,NULL);//没有写者了,向读者放行}ReleaseSemaphore(WriteMutex,1,NULL);//退出wfirst临界区ExitThread(0);//关闭写者线程return 0;}bool CreateReader(int StartTime,int WorkTime) {DWORD dwThreadID;Person *pPerson = &Persons[NumPerson];pPerson->StartTime = StartTime;pPerson->WorkTime = WorkTime;pPerson->Type = READER;NumPerson++;// 创建一个读者的新线程pPerson->Thread =CreateThread(NULL,0,ReaderProc,(LPVOID)pPerson,0,&dwThreadID);if(pPerson->Thread == NULL)return false;return true;}bool CreateWriter(int StartTime,int WorkTime)9沈阳理工大学课程设计专用纸 No1 {DWORD dwThreadID;if(NumPerson >= MAX_PERSON)return false;Person *pPerson = &Persons[NumPerson];pPerson->StartTime = StartTime;pPerson->WorkTime = WorkTime;pPerson->Type = WRITER;NumPerson++;// 创建一个写者的新线程pPerson->Thread =CreateThread(NULL,0,WriterProc,(LPVOID)pPerson,0,&dwThreadID);if(pPerson->Thread == NULL)return false;return true;}10沈阳理工大学课程设计专用纸 No1 六、运行结果图6.1 运行结果结果分析:顺序开始时间(s) 执行时间(s) 1 1 3Reader 2 3 53 15 2Writer 1 2 52 5 5表6.1如上表,第一个读者1到达时间是第1s,执行时间是3s,即在第4s的时候结束,而在第2s的时候就写者1到达。

相关主题