操作系统课程设计读者写者问题Word文档格式.docx
《操作系统课程设计读者写者问题Word文档格式.docx》由会员分享,可在线阅读,更多相关《操作系统课程设计读者写者问题Word文档格式.docx(17页珍藏版)》请在冰豆网上搜索。
写者优先与读者不同之处在于一旦一个写者到来,它应该尽快对文件进行写操作,如果有一个写者在等待,则新到来的读者不允许进行读操作。
为此应当填加一个整形变量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。
(二)原理及算法描述;
写者优先原理图:
读者优先原理图:
算法描述:
读者优先的附加限制:
如果读者申请进行读操作时已有另一个读者正在进行读操作,则该读者可直接开始读操作。
写者优先的附加限制:
如果一个读者申请进行读操作时已有另一个写者在等待访问共享资源,则该读者必须等到没有写者处于等待状态后才能开始读操作。
(三)开发环境;
(四)重要算法和设计思路描述;
(五)程序实现---数据结构;
相关WindowsAPI说明:
CreateThread:
创建一个在调用进程的地址空间中执行的线程。
ExitThread
Sleep:
对指定的时间间隔挂起当前的执行线程
CreateMutex:
创建有名或者无名的互斥对象
ReleaseMutex:
WaitForSingleObject:
当发生
(1)指定对象处于信号态
(2)超时则该函数返回
WaitForMultipleObject:
任意一个或全部指定对象处于信号态或超时间隔已过时,返回
CreateSemapore:
创建一个有名或无名信号对象。
ReleaseSemapore:
InitializeCriticalSection:
初始化临界区对象
EnterCriticalSection:
等待指定临界区对象的所有权。
当调用线程被赋予所有权时,返回。
LeaveCriticalSection:
该函数释放指定临界区对象的所有权。
(六)程序实现---程序清单;
#include<
windows.h>
//#include<
ctype.h>
stdio.h>
string.h>
stdlib.h>
malloc.h>
#include<
iostream>
usingnamespacestd;
#defineMAX_PERSON100//最多100人
#defineREADER0//读者
#defineWRITER1//写者
#defineEND-1//结束
//#defineRREADER
//#defineWWRITER
typedefstruct
{
HANDLEm_hThread;
//定义处理线程的句柄
intType;
//进程类型(读写)
intStartTime;
//开始时间
intWorkTime;
//运行时间
intID;
//进程号
}Person;
PersonPersons[MAX_PERSON];
intNumOfPerson=0;
longCurrentTime=0;
//基本时间片数
intPersonLists[]={//进程队列
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,
};
intNumOfReading=0;
intNumOfWriteRequest=0;
//申请写进程的个数
HANDLEReadSemaphore;
//读者信号
HANDLEWriteSemaphore;
//写者信号
boolfinished=false;
//所有的读完成
//boolwfinished=false;
//所有的写完成
voidCreatePersonList(int*pPersonList);
boolCreateReader(intStartTime,intWorkTime,intID);
boolCreateWriter(intStartTime,intWorkTime,intID);
DWORDWINAPIReaderProc(LPVOIDlpParam);
DWORDWINAPIWriterProc(LPVOIDlpParam);
intmain()
ReadSemaphore=CreateSemaphore(NULL,1,100,NULL);
//创建信号量,当前可用的资源数为1,最大为100
/*HANDLECreateSemaphore(
LPSECURITY_ATTRIBUTESlpSemaphoreAttributes,//lpSemaphoreAttributes为安全属性
LONGlInitialCount,//lInitialCount为Semaphore的初始值
LONGlMaximumCount,//lMaximumCount为最大值
LPCTSTRlpName//lpName为Semaphore对象的名字,NULL表示创建匿名Semaphore
);
*/
WriteSemaphore=CreateSemaphore(NULL,1,100,NULL);
CreatePersonList(PersonLists);
//创建所有读者写者
cout<
<
"
创建所有的读者写者"
\n...\n"
;
CurrentTime=0;
while(true)
{
CurrentTime++;
Sleep(300);
//300ms
cout<
当前时间="
CurrentTime<
endl;
if(finished)return0;
}
//return0;
}
voidCreatePersonList(int*pPersonLists)
inti=0;
int*pList=pPersonLists;
boolRet;
while(pList[0]!
=END)
switch(pList[1])
{
caseREADER:
Ret=CreateReader(pList[2],pList[3],pList[0]);
break;
caseWRITER:
Ret=CreateWriter(pList[2],pList[3],pList[0]);
}
if(!
Ret)
printf("
CreatePerson%diswrong\n"
pList[0]);
pList+=4;
//寻找下一个读者或者写者
boolCreateReader(intStartTime,intWorkTime,intID)
DWORDdwThreadID;
if(NumOfPerson>
=MAX_PERSON)
returnfalse;
Person*pPerson=&
Persons[NumOfPerson];
pPerson->
ID=ID;
StartTime=StartTime;
WorkTime=WorkTime;
Type=READER;
NumOfPerson++;
//新建进程
m_hThread=CreateThread(NULL,0,ReaderProc,(LPVOID)pPerson,0,&
dwThreadID);
/*HANDLECreateThread(
LPSECURITY_ATTRIBUTESlpThreadAttributes,//pointertosecurityattributes安全属性
DWORDdwStackSize,//initialthreadstacksize堆栈大小
LPTHREAD_START_ROUTINElpStartAddress,//pointertothreadfunction函数指针
LPVOIDlpParameter,//argumentfornewthread
DWORDdwCreationFlags,//creationflags
LPDWORDlpThreadId//pointertoreceivethreadID
if(pPerson->
m_hThread==NULL)
returnfalse;
returntrue;
boolCreateWriter(intStartTime,intWorkTime,intID)
{
=MAX_PERSON)
Type=WRITER;
m_hThread=CreateThread(NULL,0,WriterProc,(LPVOID)pPerson,0,&
DWORDWINAPIReaderProc(LPVOIDlpParam)//读过程
Person*pPerson=(Person*)lpParam;
//等待启动时间
while(CurrentTime!
=pPerson->
StartTime)
//读操作还没有到达执行时间,则等待
printf("
Reader%disRequesting...\n"
pPerson->
ID);
\n\n************************************************\n"
);
//等待写者请求
//该语句在写者优先的时候是认为写者优先级高于读者,在有写者的时候读者需要等候,而在读者优先的时候,不用判断是否存在写者,有读者时即开始读操作。
while(NumOfWriteRequest!
=0)
//NumOfWriteRequest!
=0表示有写者在等待,不能读
//等待ReadSemaphore读信号,即当ReadSemaphore有信号时等待结束,相当于p操作
WaitForSingleObject(ReadSemaphore,INFINITE);
/*DWORDWaitForMultipleObjects(
CONSTHANDLE*lpHandles,//pointertotheobject-handlearray
DWORDdwMilliseconds//time-outintervalinmilliseconds
if(NumOfReading==0)
{
//当第一个读者到了,如果WriteSemaphore信号灯灭了,说明有写者在写,读者必须等待,即互斥写操作
WaitForSingleObject(WriteSemaphore,INFINITE);
NumOfReading++;
//还有读者,但是允许下一个读进程读取,相当于V操作
ReleaseSemaphore(ReadSemaphore,1,NULL);
/*BOOLReleaseSemaphore(
HANDLEhSemaphore,//lpReleaseCount参数表示要增加的数值
LONGlReleaseCount,//lpPreviousCount参数用于返回之前的计算值,如果不需要可以设置为NULL
LPLONGlpPreviousCount
//启动读者
StartTime=CurrentTime;
Reader%disReadingtheCriticalSection...\n"
while(CurrentTime<
StartTime+pPerson->
WorkTime)
//..执行读操作
Reader%disExit...\n"
NumOfReading--;
if(NumOfReading==0)
ReleaseSemaphore(WriteSemaphore,1,NULL);
//此时没有读者,可以写
ID==6)finished=true;
//所有的读写完成
ExitThread(0);
return0;
DWORDWINAPIWriterProc(LPVOIDlpParam)
StartTime)
Writer%disRequesting...\n"
NumOfWriteRequest++;
//在写者优先的时候需要用自加来初始信号值,而在读者优先的时是通过读者操作来控制信号值
WaitForSingleObject(WriteSemaphore,INFINITE);
//启动写者
Writer%disWrittingtheCriticalSection...\n"
//..执行写操作
Writer%disExit...\n"
NumOfWriteRequest--;
ReleaseSemaphore(WriteSemaphore,1,NULL);
//所有的读写完成
(七)总结;
本次的操作系统课程设计,收获还是很大的。
读者写者问题是一个经典的多线程的问题,图书馆和网上都有很多资料,我也看了很多这方面的资料,应该说这个课程设计为我更加深入的研究开了一个很好的头。
验收的老师是路强老师,他当时问我怎么保证window下p,v操作的原子性,说实在的,我一直研究的是我程序的算法和实现,还真没考虑过我用的底层API函数的具