哲学家就餐问题,在网上看到一份代码,学习。。
#include <windows.h> //HADNDLE
#include <process.h>
//#include <time.h> //time(0)
//#include <stdlib.h>
#include "iostream"
using namespace std;
const unsigned int N=5; //哲学家数目
const int THINKING=1; //标记当前哲学家的状态,1表示思考(饱的)
const int HUNGRY=2; //2表示得到饥饿,3表示正在吃饭
const int EATING=3;
HANDLE hPhilosopher[N];
HANDLE semaphore[N];
HANDLE mutex; //typedef void* HANDLE
DWORD WINAPI philosopherProc(LPVOID lpParameter) //返回DWORD(32位数据)的API函数
//typedef unsigned long DWORD
//typedef WINAPI __stdcall 函数参数入栈方式从右到左,一般导出函数时用。
//typedef void* LPVOID
{
int myid;
char idStr[128];
cout << int(<span style="font-family: Arial, Helvetica, sans-serif;">lpParameter</span>) << endl;
return NULL;
}
int main()
{
//srand(time(0));
mutex = CreateMutex(NULL, false, NULL); //创建一个互斥变量
for (int i = 0; i < N; i++)
{
semaphore[i] = CreateSemaphore(NULL, 1, 1, NULL); //创建一个新的信号量
hPhilosopher[i] = CreateThread(NULL, 0, //线程安全属性,堆栈大小
philosopherProc, LPVOID(i), //线程函数,线程参数(这里,把i转成LPVOID传递)
CREATE_SUSPENDED, 0); //线程创建属性(这里是挂起,所以下面有唤起),线程ID
}
for (int i = 0; i < N; i++)
{
ResumeThread(hPhilosopher[i]); //线程恢复函数
}
Sleep(2000);//给时间线程执行
return 0;
}
1. 看到一些不熟悉的关键字比如HANDLE之类的,不要紧,它很可能就是你熟悉东西的封装,只是为了好表示而已。在vs2012中,鼠标放到该关键字上,会有定义显示。
2. 参数的传递:LPVOID(i), int(lpParameter)。先讲i转成void*。因为void*是地址,i是整数,整数可以表示地址,当然可以转成void*型。int(lpParameter),再把int型转回来。这其实就传递了一个int 型参数 i 嘛。至于这样做的好处,后面再慢慢体会。。
3. 在最初编译这个工程时出现了奇奇怪怪让人摸不着头脑的错误。原来是里面某些中文编码的问题。解决方法:
4. 在创建线程时,使用了CREATE_SUSPENDED参数,创建时挂起,所以后面使用了唤醒。
实验结果:
结果很随机。第一个 应该是冲突了cout<<int(lpParameter)后还没得及执行<<endl,就被抢占了。
5. 最后Sleep(2000)必须要有。如果没有,主线程很快终止,其创建的次线程也没有机会执行就被终止了。