ICode9

精准搜索请尝试: 精确搜索
首页 > 系统相关> 文章详细

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

2021-07-20 13:34:35  阅读:269  来源: 互联网

标签:就餐 right 进程同步 int 问题 chopsticks printf sem left


问题描述

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

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

初始解法:

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

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有