哲学家就餐问题——多线程代码学习

哲学家就餐问题,在网上看到一份代码,学习。。

#include   //HADNDLE
#include 
//#include   //time(0)
//#include 
#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(lpParameter) << 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. 在最初编译这个工程时出现了奇奇怪怪让人摸不着头脑的错误。原来是里面某些中文编码的问题。解决方法:

哲学家就餐问题——多线程代码学习_第1张图片


4.  在创建线程时,使用了CREATE_SUSPENDED参数,创建时挂起,所以后面使用了唤醒。

实验结果:

哲学家就餐问题——多线程代码学习_第2张图片哲学家就餐问题——多线程代码学习_第3张图片


结果很随机。第一个 应该是冲突了cout<

5. 最后Sleep(2000)必须要有。如果没有,主线程很快终止,其创建的次线程也没有机会执行就被终止了。


你可能感兴趣的:(哲学家就餐问题——多线程代码学习)