.2 哲学家进餐问题

问题描述:
5 个哲学家用一生的时间吃饭和思考。他们共用一张圆桌,每人都有一张椅 子,桌上放着 5 支筷子。每个哲学家感到饥饿时,会试图拿起左右的两只筷子, 每位哲学家每次只能拿起一只筷子。当每位哲学家同时有两支筷子的时候,他可 以吃饭。当他吃完后,他会放下筷子,并开始思考。


实验内容

  1. 根据哲学家进程间的相互制约关系,设置合理的信号量及信号量初值。
  2. 创建 5 个线程,分别模拟 5 个哲学家进程。
  3. 在哲学家线程之间通过对信号量的 P,V 操作,实现线程之间的同步关系。

解决方案

  1. 仅当哲学家左右手筷子都拿起时,才能进餐  
  2. 规定奇数好哲学家先拿左手筷子,再拿右手筷子;而偶数号哲学家相反  
  3. 最多允许 4 位哲学家同时去拿左筷子,最终能保证至少有一位哲学家能 进餐,并在用完后释放两只筷子供其他人使用。
  4. 此次实验代码采用第一种解决方式

实验步骤

设置哲学家就餐状态\ #define N 5            //哲学家数量

#define LEFT (i+N-1)%N //第 i 位哲学家的左边 筷子 #define RIGHT (i)%N  //第 i 位哲学家的右边筷子 

//哲学家状态   int state[N];

#define STATE_THINKING 11  

//思考 #define STATE_EATING 12  

 //吃饭 #define STATE_HUNGRY 13    

//饥饿 pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER, s[N];  //信号量   筷子的信号量

 

检查哲学家的状态函数,并对其进行相应操作

如思考、吃饭以及饥饿  void checkState(int i)   {    …… }


具体代码

#include <stdio.h>  
#include <stdlib.h>  
#include <memory.h>  
#include <pthread.h>  
#include <errno.h>  
#include <math.h>  
#define N 5 //哲学家数量
#define LEFT (i+N-1)%N //第i位哲学家的左边
#define RIGHT (i)%N //第i位哲学家的右边


int state[N]; //哲学家状态
#define STATE_THINKING 0 //思考
#define STATE_EATTING 1 //饭
#define STATE_HUNGRY 2 //
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER, s[N]; //两个信号量  这两个信号量代表的内容分别是 哲学家状态信号量/筷子信号量

int takeForks(int i)//检查哲学家的状态,并根据状态进行相应操作
{
	pthread_mutex_lock(&s[LEFT]);  //对左筷子上锁(哲学家拿起左边筷子)
	   if (pthread_mutex_trylock(&s[RIGHT]) == EBUSY)  //如果右边筷子不可拿
	{     
	   pthread_mutex_unlock(&s[LEFT]);  //释放左筷子 
	 pthread_mutex_lock(&mutex);	  //更改状态
	 state[i]=STATE_HUNGRY;	     //无法申请筷子,饥饿状态下等待
	 pthread_mutex_unlock(&mutex);
	return 0;
	    }  
         else
		{
	//	printf("philosopher %d get the %d chopstick\n",i,i);  
       	        pthread_mutex_lock(&mutex);   
		state[i]=STATE_EATTING;    //两只筷子都拿到,更改状态
		pthread_mutex_unlock(&mutex);
		return 1;
		}
}

void putForks(int i)//放下左右筷子,并更改状态到思考
{
	pthread_mutex_unlock(&s[LEFT]);   
     //   printf("philosopher %d realse the %d chopstick\n",i,LEFT);  
        pthread_mutex_unlock(&s[RIGHT]); 
      //  printf("philosopher %d realse the %d chopstick\n",i,i);  
	pthread_mutex_lock(&mutex);	
	state[i]=STATE_THINKING;
	pthread_mutex_unlock(&mutex);
}

void think(int i)   //思考完毕后更改状态为饥饿
{
	 printf("哲学家 %d 正在思考......\n",i);  
	 sleep(1);
	pthread_mutex_lock(&mutex);
	state[i]=STATE_HUNGRY;
	pthread_mutex_unlock(&mutex);
}

void eat(int i)  //吃饭完毕后放筷子
{
	printf("哲学家 %d 正在吃饭.....\n",i);
	sleep(1);
	putForks(i);
}
//检查哲学家的状态,如思考、吃饭以及饥饿,并进行相应操作
void checkState(int i)
{
	switch(state[i]){
	case STATE_EATTING:
		eat(i);
		break;
	case STATE_THINKING:
		think(i);
		break;
	case STATE_HUNGRY:   //如果
		takeForks(i);
		break;
	default: 
		printf("哲学家%d状态出错!\n",i);
		break;
		}
}

//哲学家线程的创建,包括思考、进餐等内容的设置
void* Philosopher(void *vargp) 
{ 
 	int i = *(int*)vargp;
	state[i]=STATE_THINKING;//初始化为思考状态	
	
	int j = 0;
	while(1)
	{
	//printf("%d   ",i);
		checkState(i);	  //不停检查哲学家状态
	}
	return NULL;  
	

}


int main()
{
	int ar[N],i;
	pthread_t thread_id[N];
        for (i = 0; i < N; i++)  
       	   pthread_mutex_init(&s[i],NULL);  
 
	//创建5个线程表示五个哲学家
	for(i=0;i<N;i++)
	{
		ar[i]=i;
		pthread_create(&thread_id[i],NULL,(void*)Philosopher,&ar[i]);//创建进程函数
			
	}
	for(i=0;i<N;i++)
	{
		//等待子进程结束,才退出主进程
		pthread_join(thread_id[i],NULL);
		
	}
	return 0;
}

 

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
哲学家进餐问题是一个经典的并发编程问题,它描述了五个哲学家围坐在一张圆桌旁,每个哲学家面前有一碗米饭和一只筷子。哲学家们交替进行思考和进餐,但是他们只能同时拿起自己左右两边的筷子才能进餐。以下是一个简单的五哲学家进餐问题的代码示例: ```python import threading class Philosopher(threading.Thread): def __init__(self, name, left_fork, right_fork): threading.Thread.__init__(self) self.name = name self.left_fork = left_fork self.right_fork = right_fork def run(self): while True: self.think() self.eat() def think(self): print(f"{self.name} is thinking.") def eat(self): # 获取左边的筷子 self.left_fork.acquire() # 获取右边的筷子 self.right_fork.acquire() print(f"{self.name} is eating.") # 放下左边的筷子 self.left_fork.release() # 放下右边的筷子 self.right_fork.release() if __name__ == "__main__": forks = [threading.Lock() for _ in range(5)] philosophers = [Philosopher(f"Philosopher {i}", forks[i], forks[(i + 1) % 5]) for i in range(5)] for philosopher in philosophers: philosopher.start() for philosopher in philosophers: philosopher.join() ``` 上述代码使用Python的`threading`模块实现了五哲学家进餐问题。每个哲学家都是一个线程,通过`acquire()`和`release()`方法来获取和释放筷子。当一个哲学家同时拿到左右两边的筷子时,他就可以进餐。否则,他需要等待其他哲学家释放筷子。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值