读者写者实验报告.docx
《读者写者实验报告.docx》由会员分享,可在线阅读,更多相关《读者写者实验报告.docx(16页珍藏版)》请在冰豆网上搜索。
读者写者实验报告
操作系统原理实验报告
实验名称:
操作系统
姓名:
XXX
学号:
xxxxxxxxxx
班级:
xxx
指导老师:
xxx
一、实验内容
在Windows2000环境下,创建一个控制台进程,此进程包含n个线程。
用这n个线程来表示n个读者或写者。
每个线程按相应测试数据文件(后面有介绍)的要求进行读写操作。
用信号量机制分别实现读者优先和写者优先的读者-写者问题。
读者-写者问题的读写操作限制(包括读者优先和写者优先):
1)写-写互斥,即不能有两个写者同时进行写操作。
2)读-写互斥,即不能同时有一个线程在读,而另一个线程在写。
,
3)读-读允许,即可以有一个或多个读者在读。
读者优先的附加限制:
如果一个读者申请进行读操作时已有另一个读者正在进行读操作,则该读者可直接开始读操作。
写者优先的附加限制:
如果一个读者申请进行读操作时已有另一写者在等待访问共享资源,则该读者必须等到没有写者处于等待状态后才能开始读操作。
运行结果显示要求:
要求在每个线程创建、发出读写操作申请、开始读写操作和结束读写操作时分别显示一行提示信息,以确定所有处理都遵守相应的读写操作限制。
二、实验目的
在Windows2000环境下,创建一个控制台进程,此进程包含n个线程。
用这n个线程来表示n个读者或写者。
每个线程按相应测试数据文件(后面有介绍)的要求进行读写操作。
用信号量机制分别实现读者优先和写者优先的读者-写者问题。
三、实验原理
1).读者优先
读者优先指的是除非有写者在写文件,否则读者不需要等待。
所以可以用一个整型变量read_count记录当前的读者数目,用于确定是否需要释放正在等待的写者线程(当read_count=O时,表明所有的读者读完,需要释放写者等待队列中的一个写者)。
每一个读者开始读文件时,必须修改read_count变量。
因此需要一个互斥对象mutex来实现对全局变量read_count修改时的互斥。
另外,为了实现写-写互斥,需要增加一个临界区对象write。
当写者发出写请求时,必须申请临界区对象的所有权。
通过这种方法,也可以实现读-写互斥,当read_count=l时(即第一个读者到来时),读者线程也必须申请临界区对象的所有权。
当读者拥有临界区的所有权时,写者阻塞在临界区对象write上。
当写者拥有临界区的所有权时,第一个读者判断完"read_count==1"后阻塞在write上,其余的读者由于等待对read_count的判断,阻塞在mutex上。
2).写者优先
写者优先与读者优先类似;不同之处在于一旦一个写者到来,它应该尽快对文件进行写操作,如果有一个写者在等待,则新到来的读者不允许进行读操作。
为此应当添加一个整型变量write_count,用于记录正在等待的写者的数目,当write_count=O时,才可以释放等待的读者线程队列。
为了对全局变量write_count实现互斥,必须增加一个互斥对象mutex3。
为了实现写者优先,应当添加一个临界区对象read,当有写者在写文件或等
待时,读者必须阻塞在read上。
·
读者线程除了要对全局变量read_count实现操作上的互斥外,还必须有一个互斥对象对阻塞,read这一过程实现互斥。
这两个互斥对象分别命名为mutex1和mutex2。
四、实验过程
在Windows2000环境下,创建一个控制台进程。
用VC++实现。
读者优先指的是除非有写者在写文件,否则读者不需要等待。
所以可以用一个整型变量read_count记录当前的读者数目,用于确定是否需要释放正在等待的写者线程(当read_count=O时,表明所有的读者读完,需要释放写者等待队列中的一个写者)。
每一个读者开始读文件时,必须修改read_count变量。
因此需要一个互斥对象mutex来实现对全局变量read_count修改时的互斥。
另外,为了实现写-写互斥,需要增加一个临界区对象write。
当写者发出写请求时,必须申请临界区对象的所有权。
通过这种方法,也可以实现读-写互斥,当read_count=l时(即第一个读者到来时),读者线程也必须申请临界区对象的所有权。
当读者拥有临界区的所有权时,写者阻塞在临界区对象write上。
当写者拥有临界区的所有权时,第一个读者判断完"read_count==1"后阻塞在write上,其余的读者由于等待对read_count的判断,阻塞在mutex上。
写者优先与读者优先类似;不同之处在于一旦一个写者到来,它应该尽快对文件进行写操作,如果有一个写者在等待,则新到来的读者不允许进行读操作。
为此应当添加一个整型变量write_count,用于记录正在等待的写者的数目,当write_count=O时,才可以释放等待的读者线程队列。
为了对全局变量write_count实现互斥,必须增加一个互斥对象mutex3。
为了实现写者优先,应当添加一个临界区对象read,当有写者在写文件或等
待时,读者必须阻塞在read上。
·
读者线程除了要对全局变量read_count实现操作上的互斥外,还必须有一个互斥对象对阻塞,read这一过程实现互斥。
这两个互斥对象分别命名为mutex1和mutex2。
结构:
头文件
定义全局变量
RP_ReaderThread()读者优先---读者线程
RP_WriterThread()读者优先---写者线程
ReaderPriority()读者优先处理函数
WP_ReaderThrea()写者优先---读者线程
WP_WriterThread()写者优先---写者线程
WriterPriority()写者优先处理函数
主函数:
包含对dat文件的读取以及函数的调用。
代码:
附录
五、实验结果
界面:
测试数据:
2W45
3R52
4R65
5W5.13
结果
读者优先
写者优先
六、实验心得体会
通过对读者写者问题的编程,对线程有了更深的了解,希望在后面的学习中懂得更多。
七、参考文献
老师提供的资料,以及互联网查阅。
八、附录
#include"windows.h"
#include
#include
#include
#include
#include
#include
#include"winbase.h"
#defineREADER'R'//读者
#defineWRITER'W'//写者
#defineINTE_PER_SEC1000//每秒时钟中断的数目
#defineMAX_THREAD_NUM64//最大线程数
intnReaderCnt=0;//读者计数
intnWriterCnt=0;//写者计数
HANDLEhWrite=:
:
CreateSemaphore(NULL,1,1,NULL);//写开始信号
HANDLEhRead=:
:
CreateSemaphore(NULL,1,1,NULL);//读开始信号
HANDLEhRCMutex=:
:
CreateMutex(NULL,FALSE,NULL);
HANDLEhWCMutex=:
:
CreateMutex(NULL,FALSE,NULL);
HANDLEhReadMutex=:
:
CreateMutex(NULL,FALSE,NULL);
//从测试数据文件中获取的线程信息
structThreadInfo
{
ThreadInfo()
{
nSerialNo=0;
cType='^';
dDelayTime=0.0;
dOpeTime=0.0;
}
intnSerialNo;//线程序号
charcType;//线程类别
doubledDelayTime;//线程延迟时间
doubledOpeTime;//线程读写操作时间
};
//读者优先---读者线程
//P:
读者线程信息
voidRP_ReaderThread(void*p)
{
intnSerialNo=((ThreadInfo*)(p))->nSerialNo;//从文件中读取线程序号
DWORDdwReadTime=(DWORD)(((ThreadInfo*)(p))->dOpeTime*INTE_PER_SEC);
DWORDdwDelay=(DWORD)(((ThreadInfo*)(p))->dDelayTime*INTE_PER_SEC);
Sleep(dwDelay);
printf("Readerthread%dsentsthereadingrequire.\n",nSerialNo);
WaitForSingleObject(hRCMutex,INFINITE);
nReaderCnt++;
if(nReaderCnt==1)
{
WaitForSingleObject(hWrite,INFINITE);
}
ReleaseMutex(hRCMutex);
printf("Readerthread%dbeginstoreadfile.\n",nSerialNo);
Sleep(dwReadTime);
printf("Readerthread%dfinishedreadingfile.\n",nSerialNo);
WaitForSingleObject(hRCMutex,INFINITE);
nReaderCnt--;
if(nReaderCnt==0)
{
ReleaseSemaphore(hWrite,1,NULL);
}
ReleaseMutex(hRCMutex);
}
//读者优先---写者线程
//P:
写者线程信息
voidRP_WriterThread(void*p)
{
intnSerialNo=((ThreadInfo*)(p))->nSerialNo;//从参数中获得信息
DWORDdwWriteTime=(DWORD)(((ThreadInfo*)(p))->dOpeTime*INTE_PER_SEC);
DWORDdwDelay=(DWORD)(((ThreadInfo*)(p))->dDelayTime*INTE_PER_SEC);
Sleep(dwDelay);
printf("Writethread%dsentsthewritingrequire.\n",nSerialNo);
WaitForSingleObject(hWrite,INFINITE);
printf("Writerthread%dbeginstowritetothefile.\n",nSerialNo);
Sleep(dwWriteTime);
printf("Writethread%dfinishedwritingtothefile.\n",nSerialNo);
ReleaseSemaphore(hWrite,1,NULL);
}
//读者优先处理函数
//file:
文件名
voidReaderPriority(char*file)
{
intnThreadCnt=0;
DWORDdwThreadID=0;
nReaderCnt=0;//初始化读写者计数
HANDLEhThreads[MAX_THREAD_NUM];
ThreadInfooThreadInfo[MAX_THREAD_NUM];
ifstreaminFile;
inFile.open(file);
printf("ReaderPriority:
\n\n");
while(inFile)
{
//读入每一个读者,写者的信息
inFile>>oThreadInfo[nThreadCnt].nSerialNo;
inFile>>oThreadInfo[nThreadCnt].cType;
inFile>>oThreadInfo[nThreadCnt].dDelayTime;
inFile>>oThreadInfo[nThreadCnt].dOpeTime;
if('^'!
=oThreadInfo[nThreadCnt].cType)
{
nThreadCnt++;
}
inFile.get();
}
//创建线程
for(inti=0;i{
if((oThreadInfo[i].cType==READER)||(oThreadInfo[i].cType=='r'))
{
hThreads[i]=CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)(RP_ReaderThread),//创建读者进程
&oThreadInfo[i],CREATE_SUSPENDED,&dwThreadID);
}
else
{
hThreads[i]=CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)(RP_WriterThread),//创建写线程
&oThreadInfo[i],CREATE_SUSPENDED,&dwThreadID);
}
}
for(i=0;i{
ResumeThread(hThreads[i]);
}
WaitForMultipleObjects(nThreadCnt,hThreads,TRUE,INFINITE);
printf("Allreaderandwriterhavefinishedoperating.\n");
}
//写者优先---读者线程
//P:
读者线程信息
voidWP_ReaderThread(void*p)
{
intnSerialNo=((ThreadInfo*)(p))->nSerialNo;//从参数中得到信息
DWORDdwReadTime=(DWORD)(((ThreadInfo*)(p))->dOpeTime*INTE_PER_SEC);
DWORDdwDelay=(DWORD)(((ThreadInfo*)(p))->dDelayTime*INTE_PER_SEC);
Sleep(dwDelay);
printf("Readerthread%dsentsthereadingrequire.\n",nSerialNo);
WaitForSingleObject(hReadMutex,INFINITE);
WaitForSingleObject(hRead,INFINITE);
WaitForSingleObject(hRCMutex,INFINITE);
nReaderCnt++;
if(nReaderCnt==1)
{
WaitForSingleObject(hWrite,INFINITE);
}
ReleaseMutex(hRCMutex);
ReleaseSemaphore(hRead,1,NULL);
ReleaseMutex(hReadMutex);
printf("Readerthread%dbeginstoreadfile.\n",nSerialNo);
Sleep(dwReadTime);
printf("Readerthread%dfinishedreadingfile.\n",nSerialNo);
WaitForSingleObject(hRCMutex,INFINITE);
nReaderCnt--;
if(nReaderCnt==0)
{
ReleaseSemaphore(hWrite,1,NULL);
}
ReleaseMutex(hRCMutex);
}
//写者优先---写者线程
//P:
写者线程信息
voidWP_WriterThread(void*p)
{
intnSerialNo=((ThreadInfo*)(p))->nSerialNo;
DWORDdwWriteTime=(DWORD)(((ThreadInfo*)(p))->dOpeTime*INTE_PER_SEC);
DWORDdwDelay=(DWORD)(((ThreadInfo*)(p))->dDelayTime*INTE_PER_SEC);
Sleep(dwDelay);
printf("Writerthread%dsentsthewritingrequire.\n",nSerialNo);
WaitForSingleObject(hWCMutex,INFINITE);
nWriterCnt++;
if(nWriterCnt==1)
{
WaitForSingleObject(hRead,INFINITE);
}
ReleaseMutex(hWCMutex);
WaitForSingleObject(hWrite,INFINITE);
printf("Writerthread%dbeginstowritetothefile.\n",nSerialNo);
Sleep(dwWriteTime);
printf("Writerthread%dfinishedwritingtothefile.\n",nSerialNo);
ReleaseSemaphore(hWrite,1,NULL);
WaitForSingleObject(hWCMutex,INFINITE);
nWriterCnt--;
if(nWriterCnt==0)
{
ReleaseSemaphore(hRead,1,NULL);
}
ReleaseMutex(hWCMutex);
}
//写者优先处理函数
//file:
文件名
voidWriterPriority(char*file)
{
intnThreadCnt=0;
DWORDdwThreadID;
HANDLEhThreads[MAX_THREAD_NUM];
ThreadInfooThreadInfo[MAX_THREAD_NUM];
nReaderCnt=0;
nWriterCnt=0;
ifstreaminFile;
inFile.open(file);
printf("Writerpriority:
\n\n");
while(inFile)
{
inFile>>oThreadInfo[nThreadCnt].nSerialNo;
inFile>>oThreadInfo[nThreadCnt].cType;
inFile>>oThreadInfo[nThreadCnt].dDelayTime;
inFile>>oThreadInfo[nThreadCnt].dOpeTime;
if('^'!
=oThreadInfo[nThreadCnt].cType)
{
nThreadCnt++;
}
inFile.get();
}
for(inti=0;i{
if((oThreadInfo[i].cType==READER)||(oThreadInfo[i].cType=='r'))
{
hThreads[i]=CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)(WP_ReaderThread),//创建读者进程
&oThreadInfo[i],CREATE_SUSPENDED,&dwThreadID);
}
else
{
hThreads[i]=CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)(WP_WriterThread),
&oThreadInfo[i],CREATE_SUSPENDED,&dwThreadID);
}
}
for(i=0;i{
ResumeThread(hThreads[i]);
}
WaitForMultipleObjects(nThreadCnt,hThreads,TRUE,INFINITE);
printf("Allreaderandwriterhavefinishedoperating.\n");
}
intmain(intargc,char*argv[])
{
charch;
while(true)
{
printf("*************************************\n");
printf("1.ReaderPriority\n");
printf("2.WriterPriority\n");
printf("3.ExittoWindows\n");
printf("*************************************\n");
printf("Enteryourchoice1,2,3:
");
do{
ch=(char)_getch();
}while(ch!
='1'&&ch!
='2'&&ch!
='3');
system("cls");
if(ch=='3')
return0;
elseif(ch=='1')
ReaderPriority("thread.dat");
else
WriterPriority("thread.dat");
printf("\nPressAnyKeytoCoutinue:
");
_getch();
system("cls");
}
return0;
}