读者写者实验报告_读者写者问题实验报告
读者写者实验报告由刀豆文库小编整理,希望给你工作、学习、生活带来方便,猜你可能喜欢“读者写者问题实验报告”。
操作系统原理 实验报告
实验名称:
姓 名:学 号:班 级:指导老师:
操作系统 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文件的读取以及函数的调用。代码:附录
五、实验结果
界面:
测试数据: 2 W 4 5 3 R 5 2 4 R 6 5 5 W 5.1 3 结果 读者优先
写者优先
六、实验心得体会
通过对读者写者问题的编程,对线程有了更深的了解,希望在后面的学习中懂得更多。
七、参考文献
老师提供的资料,以及互联网查阅。
八、附录
#include “windows.h” #include #include #include #include #include #include #include “winbase.h”
#define READER 'R' // 读者 #define WRITER 'W' // 写者
#define INTE_PER_SEC 1000 // 每秒时钟中断的数目 #define MAX_THREAD_NUM 64 // 最大线程数 int nReaderCnt = 0;// 读者计数 int nWriterCnt = 0;// 写者计数
HANDLE hWrite = ::CreateSemaphore(NULL, 1, 1, NULL);// 写开始信号
HANDLE hRead = ::CreateSemaphore(NULL, 1, 1, NULL);// 读开始信号
HANDLE hRCMutex = ::CreateMutex(NULL, FALSE, NULL);HANDLE hWCMutex = ::CreateMutex(NULL, FALSE, NULL);HANDLE hReadMutex = ::CreateMutex(NULL, FALSE, NULL);// 从测试数据文件中获取的线程信息 struct ThreadInfo { ThreadInfo(){ nSerialNo = 0;cType = '^';dDelayTime = 0.0;dOpeTime = 0.0;} int nSerialNo;// 线程序号 char cType;// 线程类别 double dDelayTime;// 线程延迟时间 double dOpeTime;// 线程读写操作时间 };// 读者优先---读者线程 // P:读者线程信息
void RP_ReaderThread(void *p){
int nSerialNo =((ThreadInfo*)(p))->nSerialNo;//从文件中读取 线程序号 DWORD dwReadTime
=
(DWORD)(((ThreadInfo*)(p))->dOpeTime
* INTE_PER_SEC);DWORD dwDelay
=
(DWORD)(((ThreadInfo*)(p))->dDelayTime
* INTE_PER_SEC);Sleep(dwDelay);printf(“Reader thread %d sents the reading require.n”,nSerialNo);WaitForSingleObject(hRCMutex, INFINITE);nReaderCnt++;if(nReaderCnt == 1){ WaitForSingleObject(hWrite, INFINITE);} ReleaseMutex(hRCMutex);printf(“Reader thread %d begins to read file.n”, nSerialNo);Sleep(dwReadTime);printf(“Reader thread %d finished reading file.n”, nSerialNo);WaitForSingleObject(hRCMutex, INFINITE);nReaderCnt--;if(nReaderCnt == 0){ ReleaseSemaphore(hWrite, 1, NULL);} ReleaseMutex(hRCMutex);} // 读者优先---写者线程 // P:写者线程信息
void RP_WriterThread(void *p){
int nSerialNo =((ThreadInfo*)(p))->nSerialNo;// 从参数中获得信息
DWORD dwWriteTime =(DWORD)(((ThreadInfo*)(p))->dOpeTime * INTE_PER_SEC);DWORD dwDelay
=
(DWORD)(((ThreadInfo*)(p))->dDelayTime
* INTE_PER_SEC);Sleep(dwDelay);printf(“Write thread %d sents the writing require.n”,nSerialNo);WaitForSingleObject(hWrite, INFINITE);printf(“Writer thread %d begins to write to the file.n”, nSerialNo);Sleep(dwWriteTime);printf(“Write thread %d finished writing to the file.n”, nSerialNo);
ReleaseSemaphore(hWrite, 1, NULL);} // 读者优先处理函数 // file:文件名
void ReaderPriority(char *file){ int nThreadCnt = 0;DWORD dwThreadID = 0;nReaderCnt = 0;// 初始化读写者计数 HANDLE hThreads[MAX_THREAD_NUM];ThreadInfo oThreadInfo[MAX_THREAD_NUM];ifstream inFile;inFile.open(file);printf(“Reader Priority:nn”);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(int i = 0;i
=
CreateThread(NULL,(LPTHREAD_START_ROUTINE)(RP_ReaderThread), // 创建读者进程 &oThreadInfo[i], CREATE_SUSPENDED, &dwThreadID);} else { hThreads[i]
=
CreateThread(0,(LPTHREAD_START_ROUTINE)(RP_WriterThread),// 创建写线程 &oThreadInfo[i], CREATE_SUSPENDED, &dwThreadID);} }
for(i = 0;i
0,NULL, ResumeThread(hThreads[i]);} WaitForMultipleObjects(nThreadCnt, hThreads, TRUE, INFINITE);printf(“All reader and writer have finished operating.n”);} // 写者优先---读者线程 // P:读者线程信息
void WP_ReaderThread(void *p){ int nSerialNo =((ThreadInfo*)(p))->nSerialNo;// 从参数中得到信息 DWORD dwReadTime
=
(DWORD)(((ThreadInfo*)(p))->dOpeTime
* INTE_PER_SEC);DWORD dwDelay
=
(DWORD)(((ThreadInfo*)(p))->dDelayTime
* INTE_PER_SEC);Sleep(dwDelay);printf(“Reader thread %d sents the reading require.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(“Reader thread %d begins to read file.n”, nSerialNo);Sleep(dwReadTime);printf(“Reader thread %d finished reading file.n”, nSerialNo);WaitForSingleObject(hRCMutex, INFINITE);nReaderCnt--;if(nReaderCnt == 0){ ReleaseSemaphore(hWrite, 1, NULL);} ReleaseMutex(hRCMutex);} // 写者优先---写者线程 // P:写者线程信息
void WP_WriterThread(void *p){ int nSerialNo =((ThreadInfo*)(p))->nSerialNo;DWORD dwWriteTime =(DWORD)(((ThreadInfo*)(p))->dOpeTime * INTE_PER_SEC);DWORD dwDelay
=
(DWORD)(((ThreadInfo*)(p))->dDelayTime
* INTE_PER_SEC);Sleep(dwDelay);printf(“Writer thread %d sents the writing require.n”,nSerialNo);WaitForSingleObject(hWCMutex, INFINITE);nWriterCnt++;if(nWriterCnt == 1){ WaitForSingleObject(hRead, INFINITE);} ReleaseMutex(hWCMutex);WaitForSingleObject(hWrite, INFINITE);printf(“Writer thread %d begins to write to the file.n”, nSerialNo);Sleep(dwWriteTime);printf(“Writer thread %d finished writing to the file.n”, nSerialNo);ReleaseSemaphore(hWrite, 1, NULL);WaitForSingleObject(hWCMutex, INFINITE);nWriterCnt--;if(nWriterCnt == 0){ ReleaseSemaphore(hRead, 1, NULL);} ReleaseMutex(hWCMutex);} // 写者优先处理函数 // file:文件名
void WriterPriority(char * file){ int nThreadCnt = 0;DWORD dwThreadID;
HANDLE hThreads[MAX_THREAD_NUM];ThreadInfo oThreadInfo[MAX_THREAD_NUM];
nReaderCnt=0;nWriterCnt=0;
ifstream inFile;inFile.open(file);printf(“Writer priority:nn”);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(int i = 0;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
printf(“All reader and writer have finished operating.n”);} int main(int argc,char *argv[]){ char ch;while(true){ printf(“*************************************n”);printf(“ 1.Reader Priorityn”);printf(“ 2.Writer Priorityn”);printf(“ 3.Exit to Windowsn”);printf(“*************************************n”);printf(“Enter your choice1,2,3: ”);do{ ch=(char)_getch();}while(ch!='1'&&ch!='2'&&ch!='3');system(“cls”);if(ch=='3')return 0;else if(ch=='1')ReaderPriority(“thread.dat”);else WriterPriority(“thread.dat”);printf(“nPre Any Key to Coutinue:”);_getch();system(“cls”);} return 0;}