关闭

多线程经典问题----考试问题

标签: 多线程同步线程
652人阅读 评论(0) 收藏 举报
分类:

1.问题描述:

1个主考官,n个学生

考官和学生陆续进入教室(没有先后之分)。等待所有学生进入教室后,考官开始发考卷

考官把考卷发给所有学生后,学生才开始答题,学生可以提前交卷,交完卷后即可离开教室。

老师等所有学生交完卷后才能离开教室。

2.问题解答:

本题和乘客乘公交车问题类似,主要考察多线程的同步和互斥。

主类和主线程如下:

#include "afxmt.h"

#define STUDENTCOUNT 10

class CExamQuestion
{
public:
	CExamQuestion(void){};
	virtual ~CExamQuestion(void){};
	void Init();

private:
	CWinThread *m_pTeacherThread;
	CWinThread *m_pStudentThreadArr[STUDENTCOUNT];
	HANDLE m_eventTeacher;
	HANDLE m_eventStudent[STUDENTCOUNT];
	CCriticalSection m_cs;
public:
	UINT InternalTeacherProc();
	UINT InternalStudentProc(int nIndex);
private:
	void OutputLog(char *format,...);
};


 

#include "StdAfx.h"
#include "ExamQuestion.h"

static UINT Teacher_Proc(LPVOID lpParam);
static UINT Student_Proc(LPVOID lpParam);

typedef struct tagThreadParam
{
	CExamQuestion *pExamQuestion;
	int index;
}ThreadParam;

void CExamQuestion::Init()
{
	// TODO: Add extra initialization here
	for(int i=0;i< STUDENTCOUNT;i++)
	{
		m_pStudentThreadArr[i] = NULL;
		m_eventStudent[i] =::CreateEvent(NULL,FALSE,FALSE,NULL);
	}

	m_pTeacherThread = NULL;
	m_eventTeacher=::CreateEvent(NULL,TRUE,FALSE,NULL);

	m_pTeacherThread = AfxBeginThread(Teacher_Proc,this,
		THREAD_PRIORITY_NORMAL,0,CREATE_SUSPENDED);
	::ResetEvent(m_eventTeacher);
	
	for(int i = 0;i<STUDENTCOUNT;i++)
	{
		ThreadParam* pParam = new ThreadParam;
		pParam->pExamQuestion = this;
		pParam->index = i; 

		m_pStudentThreadArr[i] = AfxBeginThread(Student_Proc,pParam,
			THREAD_PRIORITY_NORMAL,0,CREATE_SUSPENDED);
		::ResetEvent(m_eventStudent[i]);
	}

	for(int i =0;i<STUDENTCOUNT;i++)
	{
		m_pStudentThreadArr[i]->ResumeThread();
	}
	srand(time(0));
	m_pTeacherThread->ResumeThread();
}



各个角色的业务逻辑如下:

static UINT Teacher_Proc(LPVOID lpParam)
{
	CExamQuestion* pExamQuestion = (CExamQuestion *)lpParam;
	return pExamQuestion->InternalTeacherProc();
}

static UINT Student_Proc(LPVOID lpParam)
{
	ThreadParam* pParam =(ThreadParam *)lpParam;
    CExamQuestion* pExamQuestion = pParam->pExamQuestion;
	int nIndex = pParam->index;
	delete pParam;
	pParam = NULL;
	return pExamQuestion->InternalStudentProc(nIndex);
}

//考官线程
UINT CExamQuestion::InternalTeacherProc()
{
	OutputLog("监考老师进入考场\n");
	//等待学生进教室
	::WaitForMultipleObjects(STUDENTCOUNT,m_eventStudent,TRUE,INFINITE);

	OutputLog("监考老师开始发卷\n");
	::Sleep(3000);
	OutputLog("监考老师发卷完毕\n");
	::SetEvent(m_eventTeacher);
    //等待学生交卷
	while(1)
	{
        Sleep(2000);
		DWORD nRet = ::WaitForMultipleObjects(STUDENTCOUNT,m_eventStudent,TRUE,200);
		if(nRet == WAIT_TIMEOUT)
		{
			OutputLog("监考老师正在巡视考场....\n");
			continue;
		}
		else
			break;
	}
	OutputLog("监考老师整理考卷完毕\n");
	Sleep(200);
	OutputLog("监考老师离开教室\n");
	return 0;
}
//考生线程
UINT CExamQuestion::InternalStudentProc(int nIndex)
{
	OutputLog("学生%d进入考场\n",nIndex);
	::SetEvent(m_eventStudent[nIndex]);

	::WaitForSingleObject(m_eventTeacher,INFINITE);//等待老师发卷
	OutputLog("学生%d开始答题\n",nIndex);

	int i = rand()%30;
	Sleep( 1000*(i+1) );
	OutputLog("学生%d答题完毕,交卷\n",nIndex);
	::SetEvent(m_eventStudent[nIndex]);
	Sleep( 50*(i+1));
	OutputLog("学生%d离开教室\n",nIndex);
	return 0;
}

//辅助函数
void CExamQuestion::OutputLog( char *format,... )
{
	char temp[1024]={0};
	va_list arg_ptr;
	va_start(arg_ptr, format);
	vsprintf(temp, format, arg_ptr);
	va_end(arg_ptr);
	
	printf(temp);
}


输出结果如下:

学生0进入考场
学生1进入考场
学生3进入考场
学生2进入考场
学生4进入考场
学生6进入考场
学生8进入考场
学生5进入考场
学生7进入考场
学生9进入考场
监考老师进入考场
监考老师开始发卷
监考老师发卷完毕
学生2开始答题
学生0开始答题
学生1开始答题
学生3开始答题
学生5开始答题
学生7开始答题
学生9开始答题
学生6开始答题
学生4开始答题
学生8开始答题
监考老师正在巡视考场....
监考老师正在巡视考场....
监考老师正在巡视考场....
监考老师正在巡视考场....
监考老师正在巡视考场....
学生2答题完毕,交卷
学生0答题完毕,交卷
学生1答题完毕,交卷
学生3答题完毕,交卷
学生5答题完毕,交卷
学生7答题完毕,交卷
学生9答题完毕,交卷
学生8答题完毕,交卷
学生4答题完毕,交卷
学生6答题完毕,交卷
学生1离开教室
学生2离开教室
学生0离开教室
学生3离开教室
学生5离开教室
学生7离开教室
学生9离开教室
学生4离开教室
学生6离开教室
学生8离开教室
监考老师整理考卷完毕
监考老师离开教室

0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:111174次
    • 积分:2164
    • 等级:
    • 排名:第18194名
    • 原创:103篇
    • 转载:42篇
    • 译文:1篇
    • 评论:6条
    最新评论