哲学家问题
有五个哲学家绕着圆桌坐,每个哲学家面前有一盘面,两人之间有一支筷子,这样每个哲学家左右各有一支筷子。哲学家有2个状态,思考或者拿起筷子吃饭。如果哲学家拿到一只筷子,不能吃饭,直到拿到2只才能吃饭,并且一次只能拿起身边的一支筷子。一旦拿起便不会放下筷子直到把饭吃完,此时才把这双筷子放回原处。如果,很不幸地,每个哲学家拿起他或她左边的筷子,那么就没有人可以吃到饭了。
解决方案1:
控制最多有4位哲学家拿起1根筷子,保证至少有一位哲学家可以吃到饭,并且在吃完后释放筷子,使其他哲学家可以吃饭。
先定义头文件;
#include<stdio.h>
#include<time.h>
#include<unistd.h>
#include<stdlib.h>
#include<pthread.h>
再定义存放筷子和哲学家的数组;
int chops[5]={0};
int phil[5]={1,2,3,4,5};
接下来是函数部分;
先初始化再判断有几位哲学家拿到了筷子
void *philos(void *arg)
{
int m=*(int *)arg;
int left=m,right=(m+1)%5;
while(1)
{
printf("哲学家%d正在思考问题\n",m);
sleep(rand()%5);
printf("哲学家%d饿了\n",m);
while(1)
{
int sum=chops[0]+chops[1]+chops[2]+chops[3]+chops[4];
if(sum<4)
break;
}
再判断几号哲学家吃饭,结束吃饭。
while(chops[left]==1);
chops[left]==1;
printf("哲学家%d拿起了%d号筷子,现在只有一只筷子,不能进餐\n",m,left);
while(chops[right]==1);
chops[right]=1;
printf("\033[0;45;47m哲学家%d拿起了%d号筷子,现在有两只筷子,开始进餐\033[0m\n",m,right);
sleep(rand()%3);
printf("\033[0;33;47m哲学家%d进餐完毕\033[0m\n",m);
chops[left]=0;
printf("哲学家%d放下了%d号筷子\n",m,left);
chops[right]=0;
printf("哲学家%d放下了%d号筷子\n",m,right);
}
}
再进行主函数部分
先进行随机数初始化和线程id的创建,再带入函数;
int main()
{
srand(time(NULL));
int i;
pthread_t pthnum[5];
void *stat;
再通过pthread_create函数创建线程;
for(i=0;i<5;i++)
if(pthread_create(&pthnum[i],NULL,philos,(void *)&phil[i])==-1)
{
printf("creat error!\n");
exit(1);
}
for(i=0;i<5;i++)
if(pthread_join(pthnum[i],(void *)&stat)==-1)
{
printf("pthread-join error!\n");
exit(1);
}
return 0;
}
解决方案2:
将哲学家分为1至5号,让奇数号哲学家先去拿他左边的筷子, 然后再拿他右边的筷子, 偶数号哲学家相反, 这样可以保证至少有一个哲学家可以拿到2个筷子进餐然后再释放2个筷子.
先写头文件和定义初始化锁;
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
pthread_mutex_t chops[5];
接下来是各种状态下的哲学家的函数部分;
思考中:
void think(int i) {
printf("I am thinking %d\n", i);
sleep(rand() % 3);
}
饥饿中:
void hungry(int i) {
printf("I am hungry %d\n", i);
sleep(rand() % 3);
}
吃饭中:
void eat(int i) {
printf("I am eating %d\n", i);
sleep(rand() % 3);
}
整体的哲学家的函数;
先带入思考和饥饿函数
void *philosopher(void *arg) {
int i = (int)arg;
think(i);
hungry(i);
再判断是否为奇数号,然后让他拿左边的筷子,再拿右边的筷子,通过锁实现;
if (i % 2 == 0)
{
pthread_mutex_lock(&chops[(i + 1) % 5]);
pthread_mutex_lock(&chops[i]);
eat(i);
pthread_mutex_unlock(&chops[i]);
pthread_mutex_unlock(&chops[(i + 1) % 5]);
}
else
{
pthread_mutex_lock(&chops[i]);
pthread_mutex_lock(&chops[(i + 1) % 5]);
eat(i);
pthread_mutex_unlock(&chops[i]);
pthread_mutex_unlock(&chops[(i + 1) % 5]);
}
return NULL;
}
最后是主函数部分;
先创建互斥锁:
int main()
{
pthread_t tid[5];
srand(time(NULL));
for (int i = 0; i < 5; ++i)
{
pthread_mutex_init(&chops[i], NULL);
}
再创建线程:
for (int i = 0; i < 5; ++i) {
pthread_create(&tid[i], NULL, philosopher, (void *)i);
}
再用pthread_join等待子线程终止:
for (int i = 0; i < 5; ++i) {
pthread_join(tid[i], NULL);
}
最后执行销毁互斥锁:
for (int i = 0; i < 5; ++i) {
pthread_mutex_destroy(&chops[i]);
}
return 0;
}