小弟找了下,弄到了个代码
解法1,应用CRITICAL_SECTION 变量解决数据共享问题~这是CSDN上的网友写的,
(原文见http://dev.)
感觉有些粗糙,有些变量声明了后面都没用过,
效率比较低,肯定不能保证最大的并发数,
而且我在测试这段代码的时候曾出现过相邻的哲学家同时进餐的状况,这显然是不合逻辑的,
所以这个算法应该有毛病,但是作为一种思路,先记下来慢慢研究~
#include "stdafx.h"
#include "Philosopher.h"
#include < process.h >
#include < time.h >
#include < fstream >
#include < string >
#include < iostream >
#include < assert.h >
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
CWinApp theApp;
using namespace std;
HANDLE hThread;
ofstream out("out.txt");
BOOL b[6];//共享数据,用于表示 5 双筷子的使用情况,FALSE代表被占用
CRITICAL_SECTION cs;
class philosopher
{
private:
int m_num; //编号
int m_index; //标识状态,0-------waiting 1-----eating 2-----thinking
public:
philosopher(int num=0) { m_num=num; m_index=2; m_lhand=TRUE; m_rhand = FALSE ;}
int GetNum() const { return m_num; }
int GetStatus() const { return m_index ; }
void ChangeStatus() ;
};
void philosopher::ChangeStatus()
{
EnterCriticalSection (&cs) ;
if(m_index==1) //eating----->thinking
{
assert(!b[m_num]);
b[m_num]=TRUE;
if( m_num==1)
{
assert(!b[5]);
b[5]= TRUE;
}
else
b[m_num-1]=TRUE;
m_index=2; // change to thinking
srand(time(NULL)*10000);
Sleep(rand()%10);
}
else if( m_index==2) //thinking
{
m_index=0; //change to waiting
}
else if( m_index==0) // waiting
{
if(m_num==1)
{
if(b[1]&&b[5])
{
b[1]=FALSE;
b[5]=FALSE;
m_index=1;
srand(time(NULL)*10000);
Sleep(rand()%10);
}
}
else
{
if(b[m_num]&&b[m_num-1])
{
b[m_num]= FALSE;
b[m_num-1]= FALSE;
m_index=1;
srand(time(NULL)*10000);
Sleep(rand()%10);
}
}
}
LeaveCriticalSection (&cs) ;
}
string PrintStatus(philosopher *pPh)
{
pPh->ChangeStatus();
int i=pPh->GetStatus();
string str;
if(i==0)
str="Waiting";
else if(i==1)
str="eating";
else str="thinking";
return str;
}
void ThreadFunc1(PVOID param)
{
while(1)
{
philosopher *pPh;
pPh=( philosopher *) param;
pPh->ChangeStatus();
}
}
void ThreadFunc2(PVOID param)
{
while(1)
{
philosopher *pPh;
pPh=( philosopher *) param;
pPh->ChangeStatus();
}
}
void ThreadFunc3(PVOID param)
{
while(1)
{
philosopher *pPh;
pPh=( philosopher *) param;
pPh->ChangeStatus();
}
}
void ThreadFunc4(PVOID param)
{
while(1)
{
philosopher *pPh;
pPh=( philosopher *) param;
pPh->ChangeStatus();
}
}
void ThreadFunc5(PVOID param)
{
while(1)
{
philosopher *pPh;
pPh=( philosopher *) param;
pPh->ChangeStatus();
}
}
int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
{
for(int j=1;j<=5;j++) b[j]=TRUE;
out<<b[1]<<b[2]<<b[3]<<b[4]<<b[5];
philosopher ph1(1),ph2(2),ph3(3),ph4(4),ph5(5);
InitializeCriticalSection (&cs) ;
_beginthread(ThreadFunc1,0,&ph1);
_beginthread(ThreadFunc2,0,&ph2);
_beginthread(ThreadFunc3,0,&ph3);
_beginthread(ThreadFunc4,0,&ph4);
_beginthread(ThreadFunc5,0,&ph5);
cout<<"press ctrl+C to exit";
while(1)
{
cout<<endl<<b[1]<<b[2]<<b[3]<<b[4]<<b[5]<<endl; // use to test
cout<<"The status at :"<<clock()<<" ms "<<endl;
cout<<"哲学家"<<ph1.GetNum() <<"状态:"<<ph1.GetNum()<<"--"<<PrintStatus(&ph1)<<endl;
cout<<"哲学家"<<ph2.GetNum() <<"状态:"<<ph2.GetNum()<<"--"<<PrintStatus(&ph2)<<endl;
cout<<"哲学家"<<ph3.GetNum() <<"状态:"<<ph3.GetNum()<<"--"<<PrintStatus(&ph3)<<endl;
cout<<"哲学家"<<ph4.GetNum() <<"状态:"<<ph4.GetNum()<<"--"<<PrintStatus(&ph4)<<endl;
cout<<"哲学家"<<ph5.GetNum() <<"状态:"<<ph5.GetNum()<<"--"<<PrintStatus(&ph5)<<endl;
Sleep(2000);
}
DeleteCriticalSection (&cs) ;
return 0;
}
解法2,用信号量,这个比上面一个好很多了,
#include "stdafx.h"
#include "Philosopher.h"
#include "windows.h"
#include < process.h >
#include < time.h >
#include < stdlib.h >
#include < stdio.h >
#include < iostream >
using namespace std;
const unsigned int PHILOSOPHER_NUM=5;
const char THINKING=1;
const char HUNGRY=2;
const char DINING=3;
// each fork has a semaphore
HANDLE semph[PHILOSOPHER_NUM];
// Mutex for printing
HANDLE mutex;
void philosopherProc(void* param);
int main(int argc, char* argv[])
{
int i;
srand(time(0));
mutex = CreateMutex(NULL, false, NULL);
for (i=0; i<PHILOSOPHER_NUM; i++)
{
semph[i] = CreateSemaphore(NULL, 1, 1, NULL);
_beginthread(philosopherProc, 0, (void*)&i);
Sleep(10);
}
Sleep(2000);
return 0;
}
void philosopherProc(void* param)
{
int myid;
char idStr[128];
char stateStr[128];
char mystate;
int ret;
unsigned int leftFork;
unsigned int rightFork;
myid = *((int*)(param));
itoa(myid, idStr, 10);
//cout << "philosopher " << myid << " begin......" << endl;
Sleep(10);
// initial state is THINKING
mystate = THINKING;
leftFork = (myid) % PHILOSOPHER_NUM;
rightFork = (myid + 1) % PHILOSOPHER_NUM;
while (true)
{
switch(mystate)
{
case THINKING:
// changing my state
mystate = HUNGRY;
strcpy(stateStr, "HUNGRY");
break;
case HUNGRY:
strcpy(stateStr, "HUNGRY");
// first test the left fork ...
ret = WaitForSingleObject(semph[leftFork], 0);
if (ret == WAIT_OBJECT_0)
{
// left fork is ok, take it up !
// then test the right fork ...
ret = WaitForSingleObject(semph[rightFork], 0);
if (ret == WAIT_OBJECT_0)
{
// right fork is also ok !
// changing my state
mystate = DINING;
strcpy(stateStr, "DINING");
}
else
{
// right fork is being used by others, so I must put down
// the left fork.
ReleaseSemaphore(semph[leftFork], 1, NULL);
}
}
break;
case DINING:
// put down both the left and right fork
ReleaseSemaphore(semph[leftFork], 1, NULL);
ReleaseSemaphore(semph[rightFork], 1, NULL);
// changing my state
mystate = THINKING;
strcpy(stateStr, "THINKING");
break;
}
// print my state
WaitForSingleObject(mutex, INFINITE);
cout << "philosopher " << myid << " is : " << stateStr << endl;
ReleaseMutex(mutex);
// sleep a random time : between 1 - 5 s
int sleepTime;
sleepTime = 1 + (int)(5.0*rand()/(RAND_MAX+1.0));
Sleep(sleepTime*10);
}
}
另一 方法
#define N 5
#define Left (i+N-1)%N
#define Right (i+1)%N
#define THINKING 0
#define HUNGRY 1
#define EATING 2
typedef int semaphore;
int state(N);
semapore mutex =1;
semaphore s(N);
void philosopher(int i){
while(TRUE){
think();
take_forks(i);
eat();
put_forks(i);
}
}
void tak_forks(int i){
down(&mutex);
state(i)=HUNGRY;
test(i);
up(&mutex);
down(&s[i]);
}
void put_forks(int i){
down(&mutex);
state(i)=THINK;
test(LEFT);
test(RIGHT);
up(&mutex);
}
void test(i){
if(state(i)==HUNGRY && state(LEFT)!=EATING && state(RIGHT)!=EATING){
state(i)=EATING;
up(&s[i])
}
}