三个同步与互斥问题之哲学家就餐
#include<stdio.h>
#include <semaphore.h>
#include<pthread.h>
//筷子作为mutex
pthread_mutex_t chopstick[5] ;
int eatnum[5]={5,5,5,5,5};
void *eat_think(void *arg)
{
int i= *(char *)arg;
int left,right; //左右筷子的编号
left=i;
right=(i+1)%5;
while(eatnum[i]>0)
{
sleep(1); //思考
pthread_mutex_lock(&chopstick[left]); //拿起左手的筷子
printf("Philosopher %dfetches chopstick %d\n", i, left);
if (0!=pthread_mutex_trylock(&chopstick[right])){ //拿起右手的筷子
pthread_mutex_unlock(&chopstick[left]); //如果右边筷子被拿走放下左手的筷子
continue; //下一次
}
printf("Philosopher %dfetches chopstick %d\n", i, right);
printf("Philosopher %d is eating.\n",i);
sleep(1); //吃饭
eatnum[i]--;
pthread_mutex_unlock(&chopstick[right]); //放下右手的筷子
printf("Philosopher %d release chopstick %d\n", i, right);
pthread_mutex_unlock(&chopstick[left]); //放下左手的筷子
printf("Philosopher %d release chopstick %d\n", i, left);
}
printf("Philosopher %d is out\n", i);
}
int main(){
pthread_t id[5]; //5个哲学家
int i;
for (i = 0; i < 5; i++)
pthread_mutex_init(&chopstick[i],NULL);
for(i=0;i<5;i++)
pthread_create(&id[i],NULL, eat_think, (void*)&i);
for(i=0;i<5;i++)
pthread_join(id[i],NULL);
return 0;
}
/*
为资源(这里是餐叉)分配一个偏序或者分级的关系,并约定所有资源都按照这种顺序获取,按相反顺序释放,而且保证不会有两个无关资源同时被同一项工作所需要。在哲学家就餐问题中,资源(餐叉)按照某种规则编号为1至5,每一个工作单元(哲学家)总是先拿起左右两边编号较低的餐叉,再拿编号较高的。用完餐叉后,他总是先放下编号较高的餐叉,再放下编号较低的。在这种情况下,当四位哲学家同时拿起他们手边编号较低的餐叉时,只有编号最高的餐叉留在桌上,从而第五位哲学家就不能使用任何一只餐叉了。而且,只有一位哲学家能使用最高编号的餐叉,所以他能使用两只餐叉用餐。当他吃完后,他会先放下编号最高的餐叉,再放下编号较低的餐叉,从而让另一位哲学家拿起后边的这只开始吃东西。
尽管资源分级能避免死锁,但这种策略并不总是实用的,特别是当所需资源的列表并不是事先知道的时候。例如,假设一个工作单元拿着资源3和5,并决定需要资源2,则必须先要释放5,之后释放3,才能得到2,之后必须重新按顺序获取3和5。对需要访问大量数据库记录的计算机程序来说,如果需要先释放高编号的记录才能访问新的记录,那么运行效率就不会高,因此这种方法在这里并不实用。
这种方法经常是实际计算机科学问题中最实用的解法,通过为分级锁指定常量,强制获得锁的顺序,就可以解决这个问题。*/
#include <semaphore.h>
#include<pthread.h>
//筷子作为mutex
pthread_mutex_t chopstick[5] ;
int eatnum[5]={5,5,5,5,5};
void *eat_think(void *arg)
{
int i= *(char *)arg;
int left,right; //左右筷子的编号
left=i;
right=(i+1)%5;
while(eatnum[i]>0)
{
sleep(1); //思考
pthread_mutex_lock(&chopstick[left]); //拿起左手的筷子
printf("Philosopher %dfetches chopstick %d\n", i, left);
if (0!=pthread_mutex_trylock(&chopstick[right])){ //拿起右手的筷子
pthread_mutex_unlock(&chopstick[left]); //如果右边筷子被拿走放下左手的筷子
continue; //下一次
}
printf("Philosopher %dfetches chopstick %d\n", i, right);
printf("Philosopher %d is eating.\n",i);
sleep(1); //吃饭
eatnum[i]--;
pthread_mutex_unlock(&chopstick[right]); //放下右手的筷子
printf("Philosopher %d release chopstick %d\n", i, right);
pthread_mutex_unlock(&chopstick[left]); //放下左手的筷子
printf("Philosopher %d release chopstick %d\n", i, left);
}
printf("Philosopher %d is out\n", i);
}
int main(){
pthread_t id[5]; //5个哲学家
int i;
for (i = 0; i < 5; i++)
pthread_mutex_init(&chopstick[i],NULL);
for(i=0;i<5;i++)
pthread_create(&id[i],NULL, eat_think, (void*)&i);
for(i=0;i<5;i++)
pthread_join(id[i],NULL);
return 0;
}
/*
为资源(这里是餐叉)分配一个偏序或者分级的关系,并约定所有资源都按照这种顺序获取,按相反顺序释放,而且保证不会有两个无关资源同时被同一项工作所需要。在哲学家就餐问题中,资源(餐叉)按照某种规则编号为1至5,每一个工作单元(哲学家)总是先拿起左右两边编号较低的餐叉,再拿编号较高的。用完餐叉后,他总是先放下编号较高的餐叉,再放下编号较低的。在这种情况下,当四位哲学家同时拿起他们手边编号较低的餐叉时,只有编号最高的餐叉留在桌上,从而第五位哲学家就不能使用任何一只餐叉了。而且,只有一位哲学家能使用最高编号的餐叉,所以他能使用两只餐叉用餐。当他吃完后,他会先放下编号最高的餐叉,再放下编号较低的餐叉,从而让另一位哲学家拿起后边的这只开始吃东西。
尽管资源分级能避免死锁,但这种策略并不总是实用的,特别是当所需资源的列表并不是事先知道的时候。例如,假设一个工作单元拿着资源3和5,并决定需要资源2,则必须先要释放5,之后释放3,才能得到2,之后必须重新按顺序获取3和5。对需要访问大量数据库记录的计算机程序来说,如果需要先释放高编号的记录才能访问新的记录,那么运行效率就不会高,因此这种方法在这里并不实用。
这种方法经常是实际计算机科学问题中最实用的解法,通过为分级锁指定常量,强制获得锁的顺序,就可以解决这个问题。*/