5个哲学家吃饭的问题

时间:2021-08-12 22:12:21
首先我是今天刚学完事件、信号量、临界区、互斥等内核对象然后结局一个5个和尚吃饭问题~
哦,错~是5个哲学家
不过我遇到几个问题我想问问各位网友~
第一个问题:我自己写了一个程序,但是只用到了临界区内核对象,我想把所学的信号量+事件+互斥一起用在一个程序里,来实现5个哲学家吃饭问题。
第二个问题:我下面写的代码请问有哪里不对,或者思路不清晰的地方吗?我已经想了半天了... ...(我有点笨哈~不过我喜欢纠结)。
第三个问题:比如我另外的进程中用信号量(和5个哲学家吃饭无关),如果当前的信号量受信,我怎么获得当前资源可用个数。
第四个问题:CreateEvent()第三个参数BOOL bInitialState表示指定事件对象创建时的初始状态,true表示受信,false表示未受信。我想问的问题是这里的受信是什么意思?受信是直接运行?未受信是直接挂起?
第五个问题:CreateEvent()第二个参数BOOL bManualReset指定师傅需要手动重置事件对象为未受信,我想问的是如果是true,怎么才能让等待这个时间上的线程都变成可调度状态?是用SetEevent()还是用ResetEvent()?

备注:我是新手~请各位朋友能说仔细一点,我害怕看不懂~这样我就有更对疑问了..
先谢谢了~

参考代码如下(才学的~写法不规范):
图片区:
5个哲学家吃饭的问题
代码区:
#include <iostream>
#include <windows.h>
#include <ctime>
using namespace std;
#define NUM 5
CRITICAL_SECTION cs;//对存在同步问题额代码段使用临界区对象
int chopstick[5]={1,1,1,1,1};//筷子抽象,1为可以用,0为不能用
int ppState[5]={0,0,0,0,0};//哲学家的状态0为思考,1为饥饿,2为进餐
DWORD WINAPI threadFun(LPVOID);
int main()
{
InitializeCriticalSection(&cs);
HANDLE philosopher[5];
int a[]={1,2,3,4,5};
for(int i=0;i<5;i++)
{
philosopher[i]=CreateThread(
NULL,
NULL,
threadFun,
&a[i],
0,
NULL);
}
while(1)
{
cout<<"-------------------------------------------------------------"<<endl;
for(int i=0;i<NUM;i++)
{
switch(ppState[i])
{
case 0:
cout <<"哲"<<i<<"正在思考  ";
break;
case 1:
cout <<"哲"<<i<<"已经饥饿  ";
break;
case 2:
cout <<"哲"<<i<<"开始进餐  ";
break;
}
}
cout <<endl;
Sleep(5000);
}
WaitForMultipleObjects(5,philosopher,true,INFINITE);

//删除对象
for(int i=0;i<5;i++)
{
CloseHandle(philosopher[i]);
}
DeleteCriticalSection(&cs);
return 0;
}
DWORD WINAPI threadFun(LPVOID lParam)
{
int i=*(int*)(lParam)-1;
srand((unsigned int)time(0));
while(1)
{
//开始饥饿
ppState[i]=1;
//检查哲学家周围是否有筷子
if(chopstick[i]==1&&chopstick[(i+1)%NUM]==1)
{
//等待吃饭
EnterCriticalSection(&cs);
//是筷子不能使用
chopstick[i]=0;
chopstick[(i+1)%NUM]=0;
LeaveCriticalSection(&cs);
}
else
{
continue;
}
//正在吃饭
ppState[i]=2;
Sleep(rand()%1000);
//吃完饭后交出筷子
chopstick[i]=1;
chopstick[(i+1)%NUM]=1;
//开始思考
ppState[i]=0;
Sleep(rand()%1000);

}
}

5 个解决方案

#1


代码没看.
问题三:semaphore的现值就是其可用资源的个数.
问题四:bInitialState参数   
             如果为TRUE,表示这个event一开始处于激发态.
             如果为FALSE,则表示这个event一开始处于非激发状态.
问题五:bmanulReset参数:
             如为FALSE,表示为个event将在变成激发状态之后,自动重置为非激发状态.
             如为TRUE,表示不会自动重置.-----此时,顺调用ResetEvent()才能将其重置为非激发状态.
             SetEvent()-------把event对象设为激发状态.
<<Win32 多线程程序设计(候捷译)>> 这本书上都有.

#2


up~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~````

#3


兄弟 网上下载一本<<Win32 多线程程序设计>>(候捷译)看一看你就啥也明白了。那5个白痴吃饭的问题也有很好的模拟。没有的话 留下邮箱 我发给你

#4


感谢~我有这个<<Win32 多线程程序设计(候捷译)>> ~我下来看看

#5


引用 3 楼 uucall007 的回复:
兄弟 网上下载一本<<Win32 多线程程序设计>>(候捷译)看一看你就啥也明白了。那5个白痴吃饭的问题也有很好的模拟。没有的话 留下邮箱 我发给你

5个白痴吃饭,我认为是5个废物,我准备看WINDOWS95大奥秘呢。嘿嘿可惜现在盲点没时间

#1


代码没看.
问题三:semaphore的现值就是其可用资源的个数.
问题四:bInitialState参数   
             如果为TRUE,表示这个event一开始处于激发态.
             如果为FALSE,则表示这个event一开始处于非激发状态.
问题五:bmanulReset参数:
             如为FALSE,表示为个event将在变成激发状态之后,自动重置为非激发状态.
             如为TRUE,表示不会自动重置.-----此时,顺调用ResetEvent()才能将其重置为非激发状态.
             SetEvent()-------把event对象设为激发状态.
<<Win32 多线程程序设计(候捷译)>> 这本书上都有.

#2


up~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~````

#3


兄弟 网上下载一本<<Win32 多线程程序设计>>(候捷译)看一看你就啥也明白了。那5个白痴吃饭的问题也有很好的模拟。没有的话 留下邮箱 我发给你

#4


感谢~我有这个<<Win32 多线程程序设计(候捷译)>> ~我下来看看

#5


引用 3 楼 uucall007 的回复:
兄弟 网上下载一本<<Win32 多线程程序设计>>(候捷译)看一看你就啥也明白了。那5个白痴吃饭的问题也有很好的模拟。没有的话 留下邮箱 我发给你

5个白痴吃饭,我认为是5个废物,我准备看WINDOWS95大奥秘呢。嘿嘿可惜现在盲点没时间