《操作系统》上机实验报告实验项目读者写者学院(部)信息学院专业计算机科学与技术班级学生姓名学号读者写者问题一.实验目的:1.熟悉读者优先和写者优先的过程。
2.更好地理解进程同步的概念及其实现方法。
二.实验要求:分别实现读者优先和写者优先。
“读-写”互斥,即不能同时有一个读者在读,同时去有一个写者在写;“写-写”互斥,即不能有两个写者同时进行写操作;“读-读”允许,即可以有两个以上的读者同时进行读操作。
三.实验内容:读者优先:如果没有写者正在操作,则读者不需要等待,用一个整型变量readcount 记录当前的读者数目,用于确定是否释放写者线程,(当readcout=0 时,说明所有的读者都已经读完,释放一个写者线程),每个读者开始读之前都要修改readcount,为了互斥的实现对readcount 的修改,需要一个互斥对象Mutex来实现互斥。
另外,为了实现写-写互斥,需要一个临界区对象write,当写者发出写的请求时,必须先得到临界区对象的所有权。
通过这种方法,可以实现读写互斥,当readcount=1 时,(即第一个读者的到来时,),读者线程也必须申请临界区对象的所有权.当读者拥有临界区的所有权,写者都阻塞在临界区对象write上。
当写者拥有临界区对象所有权时,第一个判断完readcount==1 后,其余的读者由于等待对readcount的判断,阻塞在Mutex上!写者优先:写者优先和读者优先有相同之处,不同的地方在:一旦有一个写者到来时,应该尽快让写者进行写,如果有一个写者在等待,则新到的读者操作不能读操作,为此添加一个整型变量writecount,记录写者的数目,当writecount=0时才可以释放读者进行读操作!为了实现对全局变量writecount的互斥访问,设置了一个互斥对象Mutex3。
为了实现写者优先,设置一个临界区对象read,当有写者在写或等待时,读者必须阻塞在临界区对象read上。
读者除了要一个全局变量readcount实现操作上的互斥外,还需要一个互斥对象对阻塞在read这一个过程实现互斥,这两个互斥对象分别为mutex1和mutex2。
四.实验结果1.实验数据:读者优先:r w r w r 写者优先:r w r w r结果展示:五.实验总结这次实验分读者优先和写者优先来处理,不仅掌握了读者写者的过程和原理,而且还了解到了读者优先和写者优先之间的联系,共同点和不同点。
写代码的过程中出现了许多的问题,最先开始没有用进程来实现,发现比较困难,而且模拟的不真实,后来有从网上面学习了一些进程的东西,借鉴了他人的一些经验完成了这次的报告。
六.实验代码#include <windows.h>#include <conio.h>#include "fstream.h"int readcount=0; //读者数目int writecount=0; //写者数目CRITICAL_SECTION RP_Write; //临界区CRITICAL_SECTION cs_Write;CRITICAL_SECTION cs_Read;struct ThreadInfo //线程信息{ int Threadhao; //线程序号char ThreadClass; //线程类别double ThreadStartTime; //线程开始时间double ThreadRunTime; //线程读写持续时间};void ReaderFun(char* file);//读者优先函数void R_ReaderThread(void *p);//处理读者优先读者线程void R_WriterThread(void *p);//处理读者优先写者线程void WriterFun(char* file);void W_ReaderThread(void *p);void W_WriterThread(void *p);int main()//主函数{char select;while (true){cout<<"1:读者优先"<<endl;cout<<"2:写者优先"<<endl;cout<<"3:退出"<<endl;cout<<" "<<endl;cout<<"请选择要进行的操作:"<<endl;do{cin>>select;if(select!='1' && select!='2' && select!='3')cout<<"你操作有误,请重试!"<<endl;}while (select!='1' && select!='2' && select!='3');system("cls");if (select=='3')return 0;//退出else if (select=='1')//调用读者优先ReaderFun("110.txt");else if(select=='2')//调用写者优先WriterFun("110.txt");cout<<"\n是否还有继续? 1. 继续 2.退出"<<endl;;do{cin>>select;if(select!='1' && select!='2' )cout<<"你操作有误,请重试!"<<endl;}while (select!='1' && select!='2');if(select=='2')return 0;// 退出system("cls");}return 0;}//读者优先函数void ReaderFun(char* file){DWORD n_thread=0; //线程数初值为0DWORD thread_ID; //线程IDDWORD wait_for_all; //等待所有线程结束//临界资源HANDLE h_Mutex;//互斥对象(h_Mutex)确保线程拥有对单个资源的互斥访问权h_Mutex=CreateMutex(NULL,FALSE,"mutex_for_readcount");HANDLE h_Thread[64]; //线程对象数组,最大64ThreadInfo thread_info[64];readcount=0;InitializeCriticalSection(&RP_Write); //初始化临界区ifstream inFile;inFile.open(file);cout<<"读者优先:\n"<<endl;while (inFile){//读入每一个读者、写者的信息inFile>>thread_info[n_thread].Threadhao>>thread_info[n_thread].ThreadClass>>thread_info[n_thread].ThreadStartTime>>thread_info[n_thread].ThreadRunTime;if (-1 == inFile.get())break;n_thread++;//线程数加一}for (int i=0;i<(int)(n_thread);i++){if (thread_info[i].ThreadClass=='r')//创建读者线程h_Thread[i]=CreateThread(NULL,0,\(LPTHREAD_START_ROUTINE)(R_ReaderThread),\&thread_info[i],0,&thread_ID);else//创建写者线程h_Thread[i]=CreateThread(NULL,0,\(LPTHREAD_START_ROUTINE)(R_WriterThread),\&thread_info[i],0,&thread_ID);}wait_for_all=WaitForMultipleObjects(n_thread,h_Thread,TRUE,-1);cout<<"所有的读者和写者线程完成操作."<<endl;}//读者优先-----读者线程void R_ReaderThread(void *p){//互斥变量HANDLE h_Mutex;h_Mutex=OpenMutex(MUTEX_ALL_ACCESS,FALSE,"mutex_for_readcount");DWORD wait_for_mutex; //等待互斥变量所有权DWORD m_delay; //延迟时间DWORD m_ThreadRunTime; //读文件持续时间int m_Threadhao; //线程序号m_Threadhao=((ThreadInfo *)(p))->Threadhao;m_delay=(DWORD)(((ThreadInfo *)(p))->ThreadStartTime*100);m_ThreadRunTime=(DWORD)(((ThreadInfo *)(p))->ThreadRunTime*100);Sleep(m_delay); //延迟等待cout<<"读者线程"<<m_Threadhao<<" 发出读请求."<<endl;//等待互斥对象通知wait_for_mutex=WaitForSingleObject(h_Mutex,-1); //等待互斥信号,保证对readcount的访问、//修改互斥readcount++; //读者数目加一if (readcount==1)EnterCriticalSection(&RP_Write);//禁止写者进入ReleaseMutex(h_Mutex);//释放互斥对象,允许下个读者继续读://读文件cout<<"读者线程"<<m_Threadhao<<" 开始读文件."<<endl;Sleep(m_ThreadRunTime);//退出线程cout<<"读者线程"<<m_Threadhao<<" 完成读文件."<<endl;wait_for_mutex=WaitForSingleObject(h_Mutex,-1); //等待互斥信号,保证对readcount的访问、修改互斥readcount--; //读者数目减少if (readcount==0)LeaveCriticalSection(&RP_Write); //如果所有读者读完,唤醒写者ReleaseMutex(h_Mutex);//释放互斥信号}//读者优先-----写者线程void R_WriterThread(void *p){DWORD m_delay; //延迟时间DWORD m_ThreadRunTime; //读文件持续时间int m_Threadhao; //线程序号//从参数中获得信息m_Threadhao=((ThreadInfo *)(p))->Threadhao;m_delay=(DWORD)(((ThreadInfo *)(p))->ThreadStartTime*100);m_ThreadRunTime=(DWORD)(((ThreadInfo *)(p))->ThreadRunTime*100);Sleep(m_delay); //延迟等待cout<<"写者线程"<<m_Threadhao<<" 发出写请求."<<endl;EnterCriticalSection(&RP_Write);//禁止下一位写者进入//写文件cout<<"写者线程"<<m_Threadhao<<" 开始写文件."<<endl;Sleep(m_ThreadRunTime);//退出线程cout<<"写者线程"<<m_Threadhao<<" 完成写文件."<<endl;LeaveCriticalSection(&RP_Write); //如果所有读者读完,唤醒写者}//写者优先处理函数void WriterFun(char* file){DWORD n_thread=0; //线程数目DWORD thread_ID; //线程IDDWORD wait_for_all; //等待所有线程结束//互斥对象HANDLE h_Mutex1, h_Mutex2, h_Mutex3;h_Mutex1 = CreateMutex(NULL, FALSE, "mutex_for_writecount");h_Mutex2 = CreateMutex(NULL, FALSE, "mutex_for_readcount");h_Mutex3 = CreateMutex(NULL, FALSE, "mutex_for_read");//线程对象数组HANDLE h_Thread[64];ThreadInfo thread_info[64];readcount=0; //初始化readcountInitializeCriticalSection(&cs_Write); //初始化临界区InitializeCriticalSection(&cs_Read);ifstream inFile;inFile.open(file); //打开文件cout<<"写者优先:\n"<<endl;while (inFile){//读入每一个读者、写者的信息inFile>>thread_info[n_thread].Threadhao>>thread_info[n_thread].ThreadClass>>thread_info[n_thread].ThreadStartTime>>thread_info[n_thread].ThreadRunTime;if(-1 == inFile.get())break;n_thread++;//线程数加一}for (int i=0;i<(int)(n_thread);i++){if (thread_info[i].ThreadClass=='r')//创建读者线程h_Thread[i]=CreateThread(NULL,0,\(LPTHREAD_START_ROUTINE)(W_ReaderThread),\&thread_info[i],0,&thread_ID);else//创建写者线程h_Thread[i]=CreateThread(NULL,0,\(LPTHREAD_START_ROUTINE)(W_WriterThread),\&thread_info[i],0,&thread_ID);}//等待所有线程结束wait_for_all=WaitForMultipleObjects(n_thread,h_Thread,TRUE,-1);cout<<"所有的读者和写者线程完成操作."<<endl;}//写者优先-----写者线程void W_WriterThread(void *p){//互斥变量HANDLE h_Mutex1;h_Mutex1 = OpenMutex(MUTEX_ALL_ACCESS,FALSE,"mutex_for_writecount");DWORD wait_for_mutex; //等待互斥变量所有权DWORD m_delay; //延迟时间DWORD m_ThreadRunTime; //读文件持时续间int m_Threadhao; //线程序号m_Threadhao=((ThreadInfo *)(p))->Threadhao;m_delay=(DWORD)(((ThreadInfo *)(p))->ThreadStartTime*100);//每秒时钟中断100次m_ThreadRunTime=(DWORD)(((ThreadInfo *)(p))->ThreadRunTime*100);Sleep(m_delay);cout<<"写者线程"<<m_Threadhao<<" 发出写请求."<<endl;wait_for_mutex=WaitForSingleObject(h_Mutex1,-1);writecount++;if (writecount==1)EnterCriticalSection(&cs_Read);ReleaseMutex(h_Mutex1);EnterCriticalSection(&cs_Write);cout<<"写者线程"<<m_Threadhao<<" 开始写文件."<<endl;Sleep(m_ThreadRunTime);cout<<"写者线程"<<m_Threadhao<<" 完成写文件."<<endl;LeaveCriticalSection(&cs_Write);wait_for_mutex=WaitForSingleObject(h_Mutex1,-1);writecount--;if(writecount == 0)LeaveCriticalSection(&cs_Read);ReleaseMutex(h_Mutex1);}//写者优先-----读者线程void W_ReaderThread(void *p){HANDLE h_Mutex2, h_Mutex3;h_Mutex2 = OpenMutex(MUTEX_ALL_ACCESS,FALSE,"mutex_for_readcount");h_Mutex3 = OpenMutex(MUTEX_ALL_ACCESS,FALSE,"mutex_for_read");DWORD wait_for_mutex, wait_for_mutex1;//等待互斥变量所有权DWORD m_delay; //延迟时间DWORD m_ThreadRunTime; //读文件持续时间int m_Threadhao; //线程序号m_Threadhao=((ThreadInfo *)(p))->Threadhao;m_delay=(DWORD)(((ThreadInfo *)(p))->ThreadStartTime*100);m_ThreadRunTime=(DWORD)(((ThreadInfo *)(p))->ThreadRunTime*100);Sleep(m_delay);cout<<"读者线程"<<m_Threadhao<<" 发出读请求."<<endl;wait_for_mutex1=WaitForSingleObject(h_Mutex3,-1);EnterCriticalSection(&cs_Read);LeaveCriticalSection(&cs_Read);ReleaseMutex(h_Mutex3);wait_for_mutex=WaitForSingleObject(h_Mutex2,-1);readcount++;if (readcount == 1)EnterCriticalSection(&cs_Write);ReleaseMutex(h_Mutex2);cout<<"读者线程"<<m_Threadhao<<" 开始读文件."<<endl;Sleep(m_ThreadRunTime);cout<<"读者线程"<<m_Threadhao<<" 完成读文件."<<endl;wait_for_mutex=WaitForSingleObject(h_Mutex2,-1);readcount--;if (readcount == 0)LeaveCriticalSection(&cs_Write);ReleaseMutex(h_Mutex2);}。