一、哲学家就餐问题描述
如下图,5个哲学家用一生的时间吃饭和思考。他们共用一张圆桌,每人都有一张椅子,桌上放着5支筷子。每个哲学家感到饥饿时,会试图拿起左右的两只筷子,每位哲学家每次只能拿起一只筷子。当每位哲学家同时有两支筷子的时候,他可以吃饭。当他吃完后,他会放下筷子,并开始思考。
我们需要保证不会出现哲学家饿死的情况发生。
二、解决方法
文章将采用以下两种方法解决哲学家就餐问题
- 要求每位哲学家同时拿起两只筷子。
- 要求座位号为奇数的哲学家先拿左手的筷子,偶数的哲学家先拿右手的筷子。
三、代码
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<pthread.h>
#include<semaphore.h>
#define Phi_Number 5
pthread_mutex_t chopstick[5] ;
void *solve1(void *arg)
{
int phi = *(int *)arg;
int left,right;
switch (phi)
{
case 1:
left = 5;
right = 1;
break;
case 2:
left = 1;
right = 2;
break;
case 3:
left = 2;
right = 3;
break;
case 4:
left = 3;
right = 4;
break;
case 5:
left = 4;
right = 5;
break;
}
while(1)
{
printf("Philosopher %d is thiking !\n",phi);
sleep(1); // thinking
pthread_mutex_lock(&chopstick[left]); // Ruquest left chopstick
time_t timep11;
time (&timep11);
printf("Philosopher %d takes left chopstick %d at %s",phi,left,asctime(gmtime(&timep11)));
if (pthread_mutex_trylock(&chopstick[right]))//return 0 if success
{
pthread_mutex_unlock(&chopstick[left]); // Release left chopstick
printf("Philosopher %d release left chopstick %d\n", phi, left);
continue;
}
time_t timep1;
time (&timep1);
printf("Philosopher %d takes right chopstick %d at %s", phi, right,asctime(gmtime(&timep1)));
printf("!!!!!!!!!!!!!!!!!!!!!Philosopher %d is eating~<>_<>~.\n",phi);
sleep(3); // eating
pthread_mutex_unlock(&chopstick[left]); // Release left chopstick
printf("Philosopher %d release left chopstick %d\n", phi, left);
pthread_mutex_unlock(&chopstick[right]); // Release right chopstick
printf("Philosopher %d release right chopstick %d\n", phi, right);
pthread_exit(0);
}
}
void *solve2(void *arg)
{
int phi = *(int *)arg;
int left,right;
switch (phi)
{
case 1:
left = 5;
right = 1;
break;
case 2:
left = 1;
right = 2;
break;
case 3:
left = 2;
right = 3;
break;
case 4:
left = 3;
right = 4;
break;
case 5:
left = 4;
right = 5;
break;
}
while(1)
{
printf("Philosopher %d is thiking !\n",phi);
sleep(1); // thinking
if(phi%2 != 0)//Odd Number
{
pthread_mutex_lock(&chopstick[left]); // Ruquest left chopstick
time_t timep11;
time (&timep11);
printf("Philosopher %d takes left chopstick %d at %s",phi,left,asctime(gmtime(&timep11)));
if (pthread_mutex_trylock(&chopstick[right]))//return 0 if success
{
pthread_mutex_unlock(&chopstick[left]); // Release left chopstick
printf("Philosopher %d release left chopstick %d\n", phi, left);
continue;
}
time_t timep1;
time (&timep1);
printf("Philosopher %d takes right chopstick %d at %s\n",phi,right,asctime(gmtime(&timep11)));
printf("!!!!!!!!!!!!!!!!!!!!!Philosopher %d is eating~<>_<>~.\n",phi);
sleep(3); // eating
pthread_mutex_unlock(&chopstick[left]); // Release left chopstick
printf("Philosopher %d release left chopstick %d\n", phi, left);
pthread_mutex_unlock(&chopstick[right]); // Release right chopstick
printf("Philosopher %d release right chopstick %d\n", phi, right);
pthread_exit(0);
}
else{
pthread_mutex_lock(&chopstick[right]); // Ruquest left chopstick
time_t timep1;
time (&timep1);
printf("Philosopher %d takes right chopstick %d at %s",phi,right,asctime(gmtime(&timep1)));
if (pthread_mutex_trylock(&chopstick[left]))//return 0 if success
{
pthread_mutex_unlock(&chopstick[right]); // Release left chopstick
printf("Philosopher %d release right chopstick %d\n", phi, right);
continue;
}
time_t timep11;
time (&timep11);
printf("Philosopher %d takes left chopstick %d at %s\n",phi,left,asctime(gmtime(&timep11)));
printf("!!!!!!!!!!!!!!!!!!!!!Philosopher %d is eating~<>_<>~.\n",phi);
sleep(3); // eating
pthread_mutex_unlock(&chopstick[right]); // Release left chopstick
printf("Philosopher %d release right chopstick %d\n", phi, right);
pthread_mutex_unlock(&chopstick[left]); // Release right chopstick
printf("Philosopher %d release left chopstick %d\n", phi, left);
pthread_exit(0);
}
}
}
int main()
{
int choose;
printf("Enter 1 for solve1,2 for solve2:\n");
scanf("%d",&choose);
pthread_t Philos[Phi_Number];
int ret[Phi_Number];
int i,j,k,m;
for (i = 0; i < Phi_Number; i++){
pthread_mutex_init(&chopstick[i],NULL);
}
int a[5] = {1,2,3,4,5};
if(choose == 1)
{
ret[0] = pthread_create(&Philos[0],NULL,&solve1, &a[0]);
ret[1] = pthread_create(&Philos[1],NULL,&solve1, &a[1]);
ret[2] = pthread_create(&Philos[2],NULL,&solve1, &a[2]);
ret[3] = pthread_create(&Philos[3],NULL,&solve1, &a[3]);
ret[4] = pthread_create(&Philos[4],NULL,&solve1, &a[4]);
//sleep(1); //指线程被调用时,占着CPU不工作,其他线程无法进入
}
if(choose == 2)
{
ret[0] = pthread_create(&Philos[0],NULL,&solve2, &a[0]);
ret[1] = pthread_create(&Philos[1],NULL,&solve2, &a[1]);
ret[2] = pthread_create(&Philos[2],NULL,&solve2, &a[2]);
ret[3] = pthread_create(&Philos[3],NULL,&solve2, &a[3]);
ret[4] = pthread_create(&Philos[4],NULL,&solve2, &a[4]);
//sleep(1); //指线程被调用时,占着CPU不工作,其他线程无法进入
}
pthread_join(Philos[0],NULL);
pthread_join(Philos[1],NULL);
pthread_join(Philos[2],NULL);
pthread_join(Philos[3],NULL);
pthread_join(Philos[4],NULL);
return 0;
}
四、运行结果
1.采用解决方案1
2.采用解决方案2