#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);
}
}
理发师问题
最新推荐文章于 2021-02-13 12:27:42 发布