经典IPC问题[哲学家就餐问题]背景介绍:
哲学家就餐问题可以这样表述,假设有五位哲学家围坐在一张圆形餐桌旁,做以下两件事情之一:吃饭,或者思考。吃东西的时候,他们就停止思考,思考的时候也停止吃东西。餐桌中间有一大碗意大利面,每两个哲学家之间有一只餐叉。因为用一只餐叉很难吃到意大利面,所以假设哲学家必须用两只餐叉吃东西。他们只能使用自己左右手边的那两只餐叉。哲学家就餐问题有时也用米饭和筷子而不是意大利面和餐叉来描述,因为很明显,吃米饭必须用两根筷子。
哲学家就餐问题的演示
哲学家从来不交谈,这就很危险,可能产生死锁,每个哲学家都拿着左手的餐叉,永远都在等右边的餐叉(或者相反)。
即使没有死锁,也有可能发生资源耗尽。例如,假设规定当哲学家等待另一只餐叉超过五分钟后就放下自己手里的那一只餐叉,并且再等五分钟后进行下一次尝试。这个策略消除了死锁(系统总会进入到下一个状态),但仍然有可能发生“活锁”。如果五位哲学家在完全相同的时刻进入餐厅,并同时拿起左边的餐叉,那么这些哲学家就会等待五分钟,同时放下手中的餐叉,再等五分钟,又同时拿起这些餐叉。
在实际的计算机问题中,缺乏餐叉可以类比为缺乏共享资源。一种常用的计算机技术是资源加锁,用来保证在某个时刻,资源只能被一个程序或一段代码访问。当一个程序想要使用的资源已经被另一个程序锁定,它就等待资源解锁。当多个程序涉及到加锁的资源时,在某些情况下就有可能发生死锁。例如,某个程序需要访问两个文件,当两个这样的程序各锁了一个文件,那它们都在等待对方解锁另一个文件,而这永远不会发生。
程序初始化了5名哲学家的线程数组
因为是5个人,最大可支持2个人同时就餐
而网上基本上都是5人在任一时刻仅一名就餐的情况
所以用WindowsApi写了这个版本。新手上路,欢迎拍砖探讨。
- //Code By Pnig0s1992
- //Date:2012,3,7
- #include <stdio.h>
- #include <Windows.h>
- #define N 5 //设置哲学家总人数
- #define LEFT (i+N-1)%N
- #define RIGHT (i+1)%N
- #define THINKING 0
- #define HUNGRY 1
- #define EATING 2
- #define MAX_SEM_COUNT 1 //设置最大信号量
- HANDLE ghSemaphore;//声明信号量句柄数组
- HANDLE SemPhliosopher[N]; //声明哲学家信号量数组
- HANDLE aThread[N];//声明线程数组
- int state[N];//声明哲学家状态记录数组
- CRITICAL_SECTION cs;
- VOID take_forks(int i);
- VOID put_forks(int i);
- VOID tryEat(int i);
- VOID WINAPI PhilosopherProc(LPARAM lpParam)
- {
- INT PhilosopherNo = (INT)lpParam;
- while(TRUE)
- {
- take_forks(PhilosopherNo);
- put_forks(PhilosopherNo);
- }
- }
- VOID take_forks(int i)
- {
- WaitForSingleObject(ghSemaphore,INFINITE);
- state[i] = HUNGRY;
- tryEat(i);
- WaitForSingleObject(SemPhliosopher[i],INFINITE);
- }
- VOID put_forks(int i)
- {
- state[i] = THINKING;
- printf("\n%d号哲学家开始思考.",i+1);
- tryEat(LEFT);
- tryEat(RIGHT);
- ReleaseSemaphore(ghSemaphore,MAX_SEM_COUNT,NULL);
- }
- VOID tryEat(int i)
- {
- if(state[i] == HUNGRY && state[LEFT] != EATING && state[RIGHT] != EATING)
- {
- state[i] == EATING;
- printf("\n\n%d号哲学家正在吃饭.",i+1);
- Sleep(1000);
- ReleaseSemaphore(SemPhliosopher[i],MAX_SEM_COUNT,NULL);
- }
- }
- int main(int argc,char * argv[])
- {
- INT index = 0;
- DWORD dwThreadID[N];
- ghSemaphore = CreateSemaphore(NULL,2,2,TEXT("Sem"));//初始和最大信号量均设置为2可以使2人同时就餐
- if(ghSemaphore == NULL)
- {
- printf("\n创建信号量失败,请检查。");
- return -1;
- }
- for(index=0;index<N;index++)
- {
- SemPhliosopher[index] = CreateSemaphore(NULL,MAX_SEM_COUNT,MAX_SEM_COUNT,NULL);
- if(SemPhliosopher[index] == NULL)
- {
- printf("\n错误:%d",GetLastError());
- return -1;
- }
- }
- for(index=0;index<N;index++)//为每个哲学家创建一个线程
- {
- aThread[index] = CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)PhilosopherProc,(LPVOID)index,0,&dwThreadID[index]);
- if(aThread[index] == NULL)
- {
- printf("\n错误:%d",GetLastError());
- return -1;
- }
- }
- WaitForMultipleObjects(N,aThread,TRUE,INFINITE);
- CloseHandle(ghSemaphore);
- for(index=0;index<N;index++)
- {
- CloseHandle(SemPhliosopher[index]);
- CloseHandle(ghSemaphore);
- CloseHandle(aThread[index]);
- }
- return 0;
- }
转载于:https://blog.51cto.com/pnig0s1992/799791