哲学家就餐问题

/*
* 问题描述:哲学家就餐
* C/C++ 语言
*
* @author Erice_s
* binbin_Erices@163.com
* @date 2017/10/21
*
*/
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

#define MAX     5         // 五个哲学家
#define LEFT  (i+MAX-1)%MAX   //队列处理  左边的哲学家
#define RIGHT (i+1)%MAX     // 右边的哲学家       


enum {THINKING,HUNGRY,EATING} state[MAX];


pthread_mutex_t mutex=PTHREAD_MUTEX_INITIALIZER,s[MAX];  //每个哲学家一个互斥量


void test(int i)
{
  if(state[i]==HUNGRY && state[LEFT]!=EATING && state[RIGHT]!=EATING)
    {
      printf("the %d of phlosopher is eating...\n",i);
      state[i] = EATING;
      sleep(rand()%5);
    } 

}


void take_fork(int i)   // 第 i 号哲学家拿叉子
{
   pthread_mutex_lock(&mutex); //可以拿筷子,进行下一步,否则阻塞
   pthread_mutex_lock(&s[i]);  //第i个哲学家可以操作资源
   state[i]=HUNGRY;
   test(i);  
   pthread_mutex_unlock(&s[i]);
   pthread_mutex_unlock(&mutex);

}

void put_fork(int i)    // 第 i 号哲学家放叉子
{
   pthread_mutex_lock(&mutex);
   state[i]=THINKING;   // 调整状态
   test(LEFT);     // 给左右吃的信号
   test(RIGHT);
   pthread_mutex_unlock(&mutex);
}

void thinking(int i)
{
   printf("the %d of phlosopher is thinking...\n",i);
   sleep(rand()%5);
}

void *dothing(void *p)   // 五个哲学家开始拿叉子
{
    int i=*(int *)p;
    for(;;){           //哲学家生活方式交替的进行思考和进餐
     thinking(i);
     take_fork(i);
     put_fork(i);
    }
}

int main(void)
{
  int i;
  pthread_t tid[MAX];

  for(i=0;i<MAX;i++)
    pthread_create(&tid[i],NULL,dothing,(void*)&i);

  for(i=0;i<MAX;i++)
    pthread_join(tid[i],NULL);

  return 0;
}

代码思想分析 :

上面的代码中,当哲学家饥饿的时候他会去拿他周围两边的叉子,当执行成功后便可以就餐。之后他放下叉子,通知周围两个人他放下了叉子。上面的代码可以保证不会有两个相邻的哲学家同时进餐。


避免死锁的解法 :

(1)至多允许有四个哲学家同时拿左边的叉子,最终能保证至少有一位哲学家能够进餐,并在其用毕时能释放两只叉子,从而使更多的哲学家能够吃饭。
(2)仅当哲学家的左右两只叉子都可以用时才允许他去吃饭。
(3)规定奇数号哲学家先拿起左边的叉子,然后再去拿右边的叉子;而偶数号哲学家相反。按照此规定,1,2号哲学家竞争1 号叉子;3,4号哲学家竞争3号叉子。五位哲学家都先竞争奇数号叉子,获得后,再去竞争偶数号叉子,最后总会有一个哲学家能获得两只叉子而吃饭。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Erice_s

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值