⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 readerwriter.cpp

📁 实现了读者与写者进程之间的同步互斥问题。
💻 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 + -