#include <windows.h>
#include <iostream>
#include <process.h>
#include <cstdlib>
#include <ctime>
#include <string>
using namespace std;
//線程函數
unsigned int __stdcall philosopher( void * );
bool think( int );
bool eat( int );
void wait( int );
void print();
int count = 0; //用於記錄輸出的次數
string phil_state[ 5 ]; //哲學家狀態(思考、等待、吃飯)
bool stick[ 5 ]; //筷子的狀態(有沒有人正在使用)
//臨界區結構變量
CRITICAL_SECTION crout; //保證輸出時不會競爭
CRITICAL_SECTION chopsticks[ 5 ]; //定義五個臨界變量,代表五根筷子
//線程函數
unsigned int __stdcall philosopher( void *k )
{
int n = ( ( int * ) k )[ 0 ];
srand( time( NULL ) );
while( true )
{
think( n );
eat( n );
}
return n;
}
//思考
bool think( int k )
{
if( phil_state[ k ] == "waiting" )
return false;
else
{
phil_state[ k ] = "thinking";
print();
return true;
}
}
//吃
bool eat( int k )
{
//只有同時獲得兩根筷子才能吃飯,否則進入等待狀態
if( stick[ k ] == true && stick[ (k + 1 ) % 5 ] == true )//若果哲學家兩邊的筷子值為true則可以獲得筷子
{
EnterCriticalSection( chopsticks + k );//獲得左邊的筷子
stick[ k ] = false;
EnterCriticalSection( chopsticks + ( k + 1 ) % 5 );//獲得右邊的筷子
stick[ (k + 1 ) % 5 ] = false;//獲得筷子后把獲得的筷子狀態變為false避免被其他人爭奪筷子
phil_state[ k ] = "eating";//把哲學家自己狀態變為eating
print();
//釋放臨界區
stick[ (k + 1 ) % 5 ] = true;
stick[ k ] = true;
phil_state[ k ] = "thinking";//哲學家放下筷子狀態變為thinking
LeaveCriticalSection( chopsticks + ( k + 1 ) % 5 );//放下右邊的筷子
LeaveCriticalSection( chopsticks + k );//放下左邊的筷子
return true;
}
else
{
wait( k );
return false;
}
}
//等待
void wait(int k)
{
phil_state[ k ] = "waiting";
print();
}
//輸出函數
void print()
{
EnterCriticalSection( &crout );
count ++;
cout << "The " << count << "th time : " << endl;
for( int i = 0; i < 5; i ++ )
cout << "Philosoper " << i + 1 << " is " << phil_state[ i ] << endl;
cout << endl;
Sleep( 3000 );
LeaveCriticalSection( &crout );
}
int main()
{
void * hthread[ 5 ];
int i;
unsigned int threadid[ 5 ];
int arg[ 5 ];
unsigned long retval;
//初始化哲學家和筷子的狀態
for( i = 0; i < 5; i ++ )
{
phil_state[ i ] = "thinking";
stick[ i ] = true;
}
//初始化臨界變量
InitializeCriticalSection( &crout );
for(i=0;i<5;i++)
{
InitializeCriticalSection( chopsticks + i );
}
//創建五個哲學家線程
for( i = 0; i < 5;i ++ )
{
arg[ i ] = i;
hthread[i]=(void *)_beginthreadex(NULL,0,philosopher,(void *)(arg + i),0,threadid+i);
if( ( int ) hthread[ i ] == -1 ) //如果線程創建失敗返回-1
{
cerr << "Create thread error :" << i <<endl;
cerr << "Error code : "<< GetLastError() <<endl;
}
}
retval = WaitForMultipleObjects( 5, hthread, true, INFINITE ); //等待多個線程
if( retval == WAIT_FAILED )
{
cerr << "Wait error,error code: "<< GetLastError() << endl;
}
for( i = 0; i < 5; i ++ )
{
if( CloseHandle( hthread[ i ] ) == false )
{
cerr << "Close thread error: " << i <<endl;
cerr << "Error code: "<< GetLastError() <<endl;
}
}
return 0;
