理发师问题

#include <Windows.h>
#include <stdio.h>
#include <process.h>
#include <tchar.h>
#include <time.h>
#include <sys/timeb.h>
#include <sys/types.h>

#define CHAIR_SIZE 2
#define BARBER_SIZE 2
#define CUSTOMER_THREAD_SIZE 2

//当前“椅子”坐了哪些顾客
int chair[CHAIR_SIZE];

//mutex用来锁定“椅子”,避免多个线程同时对“椅子”进行读写
HANDLE mutex, empty, full;

DWORD WINAPI BarberThread(PVOID pvParam);//理发师线程
DWORD WINAPI CustomerThread(PVOID pvParam);//生成顾客的线程
void initRand();

int main(int argc, char **argv){
	//对变量先进行初始化
	memset(chair, 0, sizeof(chair));
	mutex = CreateMutex(NULL, 0, NULL);

	HANDLE flag;
	DWORD threadId;
	for (int i = 0; i < BARBER_SIZE; i++){
		flag = CreateThread(NULL, 0, BarberThread, NULL, 0, &threadId);
		if (flag)
			printf("Barber thread %d created.\n", threadId);
		else
			printf("Error %d while creating barber thread\n", GetLastError());
		CloseHandle(flag);
	}

	for (int i = 0; i < CUSTOMER_THREAD_SIZE; i++){
		flag = CreateThread(NULL, 0, CustomerThread, NULL, 0, &threadId);
		if (flag)
			printf("Customer thread %d created.\n", threadId);
		else
			printf("Error %d while creating custom thread\n", GetLastError());
		CloseHandle(flag);
	}
	empty = CreateSemaphore(NULL, 2, 2, NULL);
	full = CreateSemaphore(NULL, 0, 2, NULL);
	while (true);
	return 0;
}

DWORD WINAPI BarberThread(PVOID pvParam){
	int threadId = GetCurrentThreadId();
	DWORD rst;
	DWORD r = 1000;
	while (true){
		initRand();//取系统当前时间做为生成随机数的种子
		rst = WaitForSingleObject(full, 1000);//等待一段时间,如果没有“顾客”来,就去睡觉
		switch (rst){
		case WAIT_OBJECT_0:
			WaitForSingleObject(mutex, INFINITE);
			printf("customer %d is moved to barber %d\n", chair[0], threadId);
			
			chair[0] = chair[1];//顾客有先来后到,保证下一个去理发的顾客是紧随刚刚那一个去理发的人来的
			if (chair[1] != 0)
				printf("customer %d is moved to chair 0\n", chair[1]);
			chair[1] = 0;

			//这一句必须放在下一句之前。如果不这样,假设两个barber线程都到这里
			//先把mutex释放了,而没有先releasesemaphore,那么如果这时候调用
			//customerthread,就会造成有“空座位”而“顾客”坐不了的情况
			ReleaseSemaphore(empty, 1, NULL);
			ReleaseMutex(mutex);
			Sleep( (rand()%2+3)*1000 );//理发中,理发时间随机3-5秒
			break;
		case WAIT_TIMEOUT:
			printf("barber %d waiting for the next customer\n", threadId);
			Sleep(0);//主动放弃剩余的时间片,去“睡觉”
			break;
		case WAIT_FAILED:
			break;
		}		
	}
}

int customerId = 1;//顾客的ID
DWORD WINAPI CustomerThread(PVOID pvParam){
	DWORD rst;
	while (true){
		//initRand();
		rst = WaitForSingleObject(empty, 10);//顾客只会等待较短时间,如果没有椅子坐,就会离开
		switch (rst){
		case WAIT_OBJECT_0:
			WaitForSingleObject(mutex, INFINITE);
			if (chair[0] == 0){
				chair[0] = customerId;
				printf("customer %d sitting on chair 0\n", customerId);
			}
			else{
				chair[1] = customerId;
				printf("customer %d sitting on chair 1\n", customerId);
			}
			customerId++;
			ReleaseMutex(mutex);
			ReleaseSemaphore(full, 1, NULL);
			break;
		case WAIT_TIMEOUT:
			WaitForSingleObject(mutex, INFINITE);
			printf("No chair for customer %d, leaving\n", customerId++);
			ReleaseMutex(mutex);
			break;
		case WAIT_FAILED:
			break;
		}
		Sleep((rand() % 3 + 1) * 1000);//每隔一段时间产生一个新顾客
	}
}

void initRand(){
	// 如果支持高性能精度计数器,则使用其初始化随机种子(微秒级)
	LARGE_INTEGER nFrequency;
	if (::QueryPerformanceFrequency(&nFrequency))
	{
		LARGE_INTEGER nStartCounter;
		QueryPerformanceCounter(&nStartCounter);
		srand((unsigned)nStartCounter.LowPart);
	}
	else // 否则使用当前系统时间初始化随机种子(毫秒级)
	{
		_timeb stb;
		_ftime(&stb);
		srand((unsigned)stb.millitm);
	}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值