系统相关
首页 > 系统相关> > 经典进程同步问题——哲学家就餐问题

经典进程同步问题——哲学家就餐问题

作者:互联网

问题描述

有五个哲学家,他们的生活方式是交替地进行思考和进餐。他们共用一张圆桌,分别坐在五张椅子上。在圆桌上有五个碗和五支筷子,平时一个哲学家进行思考,饥饿时便试图取用其左、右最靠近他的筷子,只有在他拿到两支筷子时才能进餐。进餐完毕,放下筷子又继续思考。

哲学家进餐问题可看作是并发进程并发执行时处理共享资源的一个有代表性的问题。

初始解法:

Var chopsitck:array[0,1,2,3,4] of semaphore=1;
/*5支筷子分别设置为初始值为1的互斥信号量*/
第i个哲学家的活动
repeat
  wait(chopstick[i]);
  wait(chopstick[(i+1)%5]);
        eat();
  signal(chopstick[i]);
  signal(chopstick[(i+1)%5]);
        think();
until false;

此算法可以保证不会有相邻的两位哲学家同时进餐。若五位哲学家同时饥饿而各自拿起了左边的筷子,这使五个信号量chopstick 均为 0,当他们试图去
拿起右边的筷子时,都将因无筷子而无限期地等待下去,即可能会引起死锁。

改进解法:

方法一:至多只允许四位哲学家同时去拿左筷子,最终能保证至少有一位哲学家能进餐,并在用完后释放两只筷子供他人使用。

方法二:仅当哲学家的左右手筷子都拿起时才允许进餐。

方法三:规定奇数号哲学家先拿左筷子再拿右筷子,而偶数号哲学家相反。

代码实现

方法一

//哲学家进餐问题方法一
#include<pthread.h>
#include<pthread.h>
#include<stdio.h>
#include<semaphore.h>
#define N 5//5个哲学家

//定义信号量以及数组
sem_t chopsticks[N];
sem_t r;
int think[N]={0,1,2,3,4};

//最多允许4个哲学家拿起筷子
void *func1(void* arg){ //void指针可以指向任意类型的数据,就是说可以用任意类型的指针对void指针赋值
	int i= *(int *)arg;
	int left=i;
	int right = (i+1)%N;
	printf("t %d is thinking.\n",i);
	sleep(5);
	printf("t %d is hungry.\n",i);	
	
	sem_wait(&r);

	sem_wait(&chopsticks[left]);
	printf("%d gets the  NO.%d ,only one,don't eat.\n",i,left);
	sem_wait(&chopsticks[right]);
	printf("%d gets the NO.%d ,has two,can eat.\n",i,right);
	//printf("%d is eating.\n",i);
		
	sleep(6);

	sem_post(&chopsticks[right]);
	printf("%d puts the NO.%d\n",i,right);
	sem_post(&chopsticks[left]);
	printf("%d puts the NO.%d\n",i,left);

	sem_post(&r);
	//printf("%d is thinking.\n",i);
	
}

void main(){
	pthread_t PHD[N];
	int m;
	for(m=0;m<N;m++){
		sem_init(&chopsticks[m],0,1);
	}
	sem_init(&r,0,4);

	int j;
	for(j=0;j<N;j++){
		pthread_create(&PHD[j],NULL,(void*)func1,&think[j]);
	}

	int k;
	for(k=0;k<N;k++){
		pthread_join(PHD[k],NULL);
	}

	for(m=0;m<N;m++){
		sem_destroy(&chopsticks[m]);
	}

	sem_destroy(&r);
}

方法二

//哲学家进餐问题方法二
#include<pthread.h>
#include<pthread.h>
#include<stdio.h>
#include<semaphore.h>
#define N 5//5个哲学家

//定义信号量以及数组
sem_t chopsticks[N],mutex;
int think[N]={0,1,2,3,4};

//同时拿起左右筷子时才允许进餐
void *func2(void* arg){
	int i= *(int *)arg;
	int left=i;
	int right = (i+1)%N;
	printf("t %d is thinking.\n",i);
	sleep(5);
	printf("t %d is hungry.\n",i);	
	
	sem_wait(&mutex);

	sem_wait(&chopsticks[left]);
	printf("%d gets the  NO.%d ,only one,don't eat.\n",i,left);
	sem_wait(&chopsticks[right]);
	printf("%d gets the NO.%d ,has two,can eat.\n",i,right);
	
	sem_post(&mutex);
		
	sleep(6);

	sem_post(&chopsticks[right]);
	printf("%d puts the NO.%d\n",i,right);
	sem_post(&chopsticks[left]);
	printf("%d puts the NO.%d\n",i,left);
	
}

void main(){
	pthread_t PHD[N];
	int m;
	for(m=0;m<N;m++){
		sem_init(&chopsticks[m],0,1);
	}
	sem_init(&mutex,0,1);

	int j;
	for(j=0;j<N;j++){
		pthread_create(&PHD[j],NULL,(void*)func2,&think[j]);
	}

	int k;
	for(k=0;k<N;k++){
		pthread_join(PHD[k],NULL);
	}

	for(m=0;m<N;m++){
		sem_destroy(&chopsticks[m]);
	}
	sem_destroy(&mutex);
}

方法三

//哲学家进餐问题方法三
#include<pthread.h>
#include<pthread.h>
#include<stdio.h>
#include<semaphore.h>
#define N 5//5个哲学家

//定义信号量以及数组
sem_t chopsticks[N];
sem_t r;
int think[N]={0,1,2,3,4};

//奇数偶数哲学家不同的拿筷顺序
void *func3(void* arg){
	int i= *(int *)arg;
	int left=i;
	int right = (i+1)%N;
	printf("t %d is thinking.\n",i);
	sleep(5);
	printf("t %d is hungry.\n",i);		
	
	if (i % 2 == 1) {//奇数哲学家,先左后右
            	sem_wait(&chopsticks[left]);
		printf("%d gets the  NO.%d ,only one,don't eat.\n",i,left);
		sem_wait(&chopsticks[right]);
		printf("%d gets the NO.%d ,has two,can eat.\n",i,right);
	
		sleep(6);

		sem_post(&chopsticks[right]);
		printf("%d puts the NO.%d\n",i,right);
		sem_post(&chopsticks[left]);
		printf("%d puts the NO.%d\n",i,left);
        } 
	else {//偶数哲学家,先右后左
            	sem_wait(&chopsticks[right]);
		printf("%d gets the  NO.%d ,only one,don't eat.\n",i,right);
		sem_wait(&chopsticks[left]);
		printf("%d gets the NO.%d ,has two,can eat.\n",i,left);
	
		sleep(6);

		sem_post(&chopsticks[left]);
		printf("%d puts the NO.%d\n",i,left);
		sem_post(&chopsticks[right]);
		printf("%d puts the NO.%d\n",i,right);
        }
	
}

void main(){
	pthread_t PHD[N];
	int m;
	for(m=0;m<N;m++){
		sem_init(&chopsticks[m],0,1);
	}
	sem_init(&r,0,4);

	int j;
	for(j=0;j<N;j++){
		pthread_create(&PHD[j],NULL,(void*)func3,&think[j]);
	}

	int k;
	for(k=0;k<N;k++){
		pthread_join(PHD[k],NULL);
	}

	for(m=0;m<N;m++){
		sem_destroy(&chopsticks[m]);
	}

	sem_destroy(&r);
}

标签:就餐,right,进程同步,int,问题,chopsticks,printf,sem,left
来源: https://blog.csdn.net/qiankendeNMY/article/details/118932922