📄 readerwriter.cpp
字号:
/*
在Windows XP环境下,创建一个控制台程序,包含n个
线程,表示n个读者或写者,每个线程按相应测试数据文件。
本程序是读者写者问题的读写操作限制:
1.写-写互斥,即不能有两个写者同时进行写操作。
2.读-写互斥,即不能同时有一个线程在读,而另一个线程在写。
3.读-读允许,即可以有一个或多个读者在读。
读者优先的附加限制:如果一个读者申请进行读操作时已有
另一个读者正在进行读操作,则该读者可直接开始读操作。
写者优先的附加限制:如果一个读者申请进行读操作时已有
另一个写者在等待访问共享资源,则该读者必须等到没有写
者处于等待状态后才能开始读操作。
本程序由:
何力 pb04210402 王成瑞 pb04210160
马平 pb04210301 张超 pb04210191
共同完成*/
#include "stdafx.h"
#include "windows.h"
#include "iostream.h"
#include "conio.h"
#include "ReaderWriter.h"
#include "vector"
using namespace std;
vector <HANDLE> p_thread;
//************************************************************************//
void main()
{
//初始化临界区
InitializeCriticalSection(&CriticalSection);
//调用用户界面函数
UserInterface();
//进程等待所有线程结束
WaitForMultipleObjects(p_thread.size(),p_thread.begin(),true,INFINITE);
cout<<"All reader and writer have finished working."<<endl;
//删除临界区
DeleteCriticalSection(&CriticalSection);
}
//******************** 用户界面函数,负责各函数的调用 *******************************//
void UserInterface(){
cout<<"********************************"<<endl;
cout<<"Please Select:"<<endl;
cout<<"\t1.Reader Priority"<<endl;
cout<<"\t2.Writer Priority"<<endl;
cout<<"\t3.Exit to Windows"<<endl;
cout<<"********************************"<<endl;
switch(_getch()){
case '1':
cout<<"You have selected Reader Priority mode."<<endl;
ReaderPriority(); //调用读者函数
break;
case '2':
cout<<"You have selected Writer Priority mode."<<endl;
WriterPriority(); //调用写者函数
break;
case '3':
exit(0); //退出程序
default:
cout<<"Error Input"<<endl;
}
}
//******************** 读者函数 ***************************************//
void ReaderPriority(){
CreatePersonList(PersonList,ReaderPriority_Mode);
}
//******************** 写者函数 ******************************************//
void WriterPriority(){
CreatePersonList(PersonList,WriterPriority_Mode);
}
//******************** 创建读者写者个人节点函数 *******************************************//
void CreatePersonList(int* pPersonList,int symbol){
if(!pPersonList[0]){ //没有读者写者的情况
cout<<"Error.There is no person!";
return;
}
int* Pointer=pPersonList;
while(Pointer[0]){
switch(Pointer[1]){
case R: //读者情况,调用创建读者的函数
CreateReader(Pointer[0],Pointer[1],Pointer[2],Pointer[3],symbol);
break;
case W: //写者情况,调用创建写者的函数
CreateWriter(Pointer[0],Pointer[1],Pointer[2],Pointer[3],symbol);
break;
}
Pointer+=4; //指针后移一个单位
}
}
//********************** 创建读者函数 **********************************//
void CreateReader(int ID,int type,int starttime,int workingtime,int symbol){
DWORD dwThreadID;
Person* pPersonQueue=&PersonQueue[NumID]; //指向人物队列
pPersonQueue->ID=ID; //ID表示该人物的编号
pPersonQueue->tpye=type; //tpye该人物的类型,是读者,还是写者
pPersonQueue->startTime=starttime; //starttime表示,开始工作的时间
pPersonQueue->workingTime=workingtime; //workingtime表示,需要工作的时间
NumID++;
if(symbol==ReaderPriority_Mode) //读者优先模式
{
//创建读者优先的读者线程
pPersonQueue->p_Thread=CreateThread(NULL,0, RP_ReaderThread, (LPVOID)pPersonQueue, 0,
&dwThreadID);
//把该线程压栈
p_thread.push_back(pPersonQueue->p_Thread);
}
else if(symbol==WriterPriority_Mode) //写者优先模式
{
//创建写者优先的读者线程
pPersonQueue->p_Thread=CreateThread(NULL,0, WP_ReaderThread, (LPVOID)pPersonQueue, 0,
&dwThreadID);
//把该线程压栈
p_thread.push_back(pPersonQueue->p_Thread);
}
if (pPersonQueue->p_Thread==NULL) { //空的情况
return;
}
}
//********************** 创建写者函数 ************************************//
void CreateWriter(int ID,int type,int starttime,int workingtime,int symbol){
DWORD dwThreadID;
Person* pPersonQueue=&PersonQueue[NumID]; //指向人物队列
pPersonQueue->ID=ID; //ID表示该人物的编号
pPersonQueue->tpye=type; //tpye该人物的类型,是读者,还是写者
pPersonQueue->startTime=starttime; //starttime表示,开始工作的时间
pPersonQueue->workingTime=workingtime; //workingtime表示,需要工作的时间
NumID++;
if(symbol==ReaderPriority_Mode) //读者优先模式
{
//创建读者优先的写者线程
pPersonQueue->p_Thread=CreateThread(NULL,0, RP_WriterThread, (LPVOID)pPersonQueue, 0,
&dwThreadID);
//把该线程压栈
p_thread.push_back(pPersonQueue->p_Thread);
}
else if(symbol==WriterPriority_Mode) //写者优先模式
{
//创建写者优先的写者线程
pPersonQueue->p_Thread=CreateThread(NULL,0, WP_WriterThread, (LPVOID)pPersonQueue, 0,
&dwThreadID);
//把该线程压栈
p_thread.push_back(pPersonQueue->p_Thread);
}
if (pPersonQueue->p_Thread==NULL) { //空的情况
cout<<"Thread is empty."<<endl;
return;
}
}
//******************** 读优先的读者线程函数 ***********************************//
DWORD WINAPI RP_ReaderThread(LPVOID lpParam){
Person* pPerson=(Person*)lpParam;
Sleep(pPerson->startTime*1000);
cout<<"Reader "<<pPerson->ID<<" send reading request."<<endl;
while(WritingNum!=0){
//线程睡眠1ms,节约CPU资源
//在调试时,最开始没有该语句,也能正常运行,但是空循环太占用CPU资源,
//加入该语句后,发现能够很好的节约CPU资源
Sleep(1);
}
cout<<"Reader "<<pPerson->ID<<" begins to read files."<<endl;
ReadingNum++; // ReadingNum 表示当前正在工作的读者数,线程开始工作后自加该计数器
Sleep(pPerson->workingTime*1000);
cout<<"Reader "<<pPerson->ID<<" finished reading files."<<endl;
ReadingNum--; //线程结束后,自减该计数器
ExitThread(0);
return 0;
}
//********************* 读优先的写者线程函数 *********************************//
DWORD WINAPI RP_WriterThread(LPVOID lpParam){
Person* pPerson=(Person*)lpParam;
Sleep(pPerson->startTime*1000);
cout<<"Writer "<<pPerson->ID<<" send writing request."<<endl;
EnterCriticalSection(&CriticalSection); // 等待指定临界区对象的所有权
while(ReadingNum!=0){ //等待没有读者进行读操作 ReadingNum表示当前正在读工作的读者数
Sleep(1); //线程睡眠1ms,节约CPU资源
}
cout<<"Writer "<<pPerson->ID<<" begins to write files."<<endl;
WritingNum++; //WritingNum 表示当前正在工作的写者数,线程开始工作后自加该计数器
Sleep(pPerson->workingTime*1000);
cout<<"Writer "<<pPerson->ID<<" finished writing files."<<endl;
LeaveCriticalSection(&CriticalSection); // 释放指定临界区对象的所有权
WritingNum--;
ExitThread(0);
return 0;
}
//********************* 写优先的读者线程函数 ************************************//
DWORD WINAPI WP_ReaderThread(LPVOID lpParam){
Person* pPerson=(Person*)lpParam;
Sleep(pPerson->startTime*1000);
cout<<"Reader "<<pPerson->ID<<" send reading request."<<endl;
//判断是否有写者进行写操作,且没有写者在等待,若有,则等待
while(WritingNum!=0 ||WriterWaitingNum!=0){
Sleep(1); //线程睡眠1ms,节约CPU资源
}
cout<<"Reader "<<pPerson->ID<<" begins to read files."<<endl;
ReadingNum++; // ReadingNum 表示当前正在工作的读者数,线程开始工作后自加该计数器
Sleep(pPerson->workingTime*1000);
cout<<"Reader "<<pPerson->ID<<" finished reading files."<<endl;
ReadingNum--; //线程结束后,自减该计数器
ExitThread(0);
return 0;
}
//********************** 写优先的写者线程函数 ****************************//
DWORD WINAPI WP_WriterThread(LPVOID lpParam){
Person* pPerson=(Person*)lpParam;
Sleep(pPerson->startTime*1000);
cout<<"Writer "<<pPerson->ID<<" send writing request."<<endl;
WriterWaitingNum++; //WriterWaitingNum 表示当前正在等待的写者数
EnterCriticalSection(&CriticalSection); // 等待指定临界区对象的所有权
//判断是否有读者进行读操作,若有,则等待
while(ReadingNum!=0){
Sleep(1); //线程睡眠1ms,节约CPU资源
}
WriterWaitingNum--; //写者开始进入写操作,不再等待,自减计数器
WritingNum++; //WritingNum 表示当前正在工作的写者数,线程开始工作后自加该计数器
cout<<"Writer "<<pPerson->ID<<" begins to write files."<<endl;
Sleep(pPerson->workingTime*1000);
cout<<"Writer "<<pPerson->ID<<" finished writing files."<<endl;
LeaveCriticalSection(&CriticalSection); // 释放指定临界区对象的所有权
WritingNum--; //线程结束后,自减该计数器
ExitThread(0);
return 0;
}
//************************************************************************//
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -