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

原创 2013年12月01日 22:56:28

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离开教室
监考老师整理考卷完毕
监考老师离开教室

python的7个经典的面试题

http://michaelyou.github.io/2015/05/19/%E7%BF%BB%E8%AF%91-7%E4%B8%AA%E7%BB%8F%E5%85%B8python%E9%9D%A...
  • u011860731
  • u011860731
  • 2015年07月19日 15:54
  • 4394

LeetCode最常见的面试笔试题总结

找了一段时间的实习,总结一下LeetCode上面试出现频率比较高的题,只总结一部分,后续还会继续更新。一、Two Sum题意是给出一个数组,输出和为k的两个数。数组为无序的。 这道题的解题思路是先把...
  • u014486880
  • u014486880
  • 2016年04月26日 23:55
  • 8178

【MySQL】20个经典面试题,全部答对月薪10k+

原文链接:http://bbs.51cto.com/thread-1470880-1.html Part2:经典题目 1、MySQL的复制原理以及流程 基本原理流程,3个线程以及之间的关联;...
  • u013252072
  • u013252072
  • 2016年10月24日 15:52
  • 69807

多线程代码 经典线程同步互斥问题 生产者消费者问题

  • 2015年06月01日 22:06
  • 16KB
  • 下载

经典多线程实例:生产者消费者问题

大部分人在理解Java的多线程这个问题有点困难,尤其是一些刚开始接触的编程语言是C语言的人。考虑到用C语言的人接触的都是一个主线程,下面给出的例子并没有太复杂的结构。主要是用来理解多线程的机制。 ...
  • Easy_Gemini
  • Easy_Gemini
  • 2012年11月23日 14:21
  • 1184

多线程经典案例——生产者/消费者问题的Java实现与详解

生产者消费者问题(英语:Producer-consumer problem),也称有限缓冲问题(英语:Bounded-buffer problem),是一个多线程同步问题的经典案例。该问题描述了两个共...
  • shengwusuoxi
  • shengwusuoxi
  • 2014年04月01日 12:37
  • 2587

java 多线程经典例子——生产者与消费者的问题

产品名称类: public class Product { //产品名称 private String name; public String getName() { return...
  • zxman660
  • zxman660
  • 2012年08月01日 14:17
  • 3173

多线程经典问题之多窗口卖票

需求:简单的卖票程序,要实现多个窗口同时买票。 一、方式一: 1、问题:为什么50张票被卖了150次? 2、出现的原因:因为num是非静态的,非静态的成员变量数据是在每个对象中都会维护一份数据的,...
  • qq_34944851
  • qq_34944851
  • 2016年08月06日 16:00
  • 198

Java经典多线程问题--生产者与消费者

今天研究了一下Java多线程,顺便写了一下多线程中的经典问题—–生产者消费者经典问题,推荐一个线程链接Java基础知识回顾–线程 这个里面其实写了生产者与消费者问题,估计在后面大家看起来比较费劲,所...
  • bug_moving
  • bug_moving
  • 2016年10月05日 15:22
  • 546

多线程通信经典问题——生产者消费者

多线程通信经典案例:生产者消费者
  • qq_22938623
  • qq_22938623
  • 2017年03月20日 22:17
  • 227
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:多线程经典问题----考试问题
举报原因:
原因补充:

(最多只允许输入30个字)