计算机操作系统

educoder平台
第二关哲学家就餐问题
书本上实例代码

//记录型信号量解决
semaphore chopstick[5]={1,1,1,1,1};//五根筷子信号量
do{
	wait(chopstick[i]);//拿起第一根筷子
	wait(chopstick([i+1)%5]);//拿起第二根筷子
	//eat,持有两根筷子,就餐时间
	signal(chopstick[i]);//放下第一根筷子
	signal(chopstick([i+1)%5]);//放下第二根筷子
	//第一位哲学家就餐完成,一直持续下去
}while(TRUE);
//and信号量机制解决
semaphore chopstick[5]={1,1,1,1,1};//五根筷子信号量
do{
	...think
	Swait(chopstick[i],chopstick([i+1)%5]);//同时拥有两根筷子
	//eat,持有两根筷子,就餐时间
	Ssignal(chopstick[i],chopstick([i+1)%5]);//放下筷子
	//第一位哲学家就餐完成,一直持续下去
}while(TRUE);

//哲学家进餐问题
#include <stdio.h>
#include <stdlib.h> 
#include <pthread.h>
#include <semaphore.h> 

static sem_t sem_chops[5];//筷子信号量 
static sem_t sem_stop;//该信号量用于等待。
//时间递增方法 
void time_add_ms(struct timeval *time, uint ms)
{
        time->tv_usec += ms * 1000; // 微秒 = 毫秒 * 1000
        if(time->tv_usec >= 1000000) // 进位,1000 000 微秒 = 1 秒
        {
                time->tv_sec += time->tv_usec / 1000000;
                time->tv_usec %= 1000000;
        }
}
//100毫秒
#define TIMEOUT_FIRST 100
//200毫秒
#define TIMEOUT_HOLD 200
//200毫秒
#define TIMEOUT_PHIEND 200
//200毫秒 
#define TIME_REPORT 200

struct timeval  begintime;      //获取的机器初始开始时间值
struct timespec first_time;     //首次获取筷子信号量
struct timespec phi_holdtime;    //保持一段时间
struct timespec report_time;    //汇报线程完成情况时间
struct timespec phi_endtime;    //哲学家线程结束绝对时间值
static int finish[5]; 

//哲学家线程没有进行有效同步控制
void* Philosopher(void *arg)
{
	int iIndex=*((int*)arg);
	int iRetWait1=-1,iRetWait2=-1;
	//iRetWait1是获取筷子资源1的结果,成功返回0,失败返回-1
	//iRetWait2是获取筷子资源2的结果,成功返回0,失败返回-1
	iRetWait1=sem_timedwait(sem_chops+iIndex,&first_time);//获取筷子时间结果
	/*begin ******哲学家线程获取筷子资源进餐*************************/ 
	
    //获取第一个筷子成功后还要保持一段时间,继续请求下一个新筷子
	sem_timedwait(&sem_stop,&phi_holdtime);
    // 取第二个筷子,最多等待的时间点是700ms
	iRetWait2=sem_timedwait(sem_chops+(iIndex+1)%5,&first_time);

	if((iRetWait1==0)&&(iRetWait2==0))
	{//检查获得两个筷子资源结果,都成功则为就餐成功
		//设置任务完成标志为1,线程结束
		finish[iIndex]=1;
		//释放筷子资源iIndex
		sem_post(&sem_chops[iIndex]);
		//释放筷子资源
		sem_post(&sem_chops[(iIndex+1)%5]);
	}
	 
	 
	 
	/*end*********************************************/
	
	
	
    //线程结束时间点:约为700MS	
	return;
}

//哲学家线程进行有效同步控制
void* PhilosopherGood(void *arg)
{
	int iIndex=*((int*)arg);
	int iRetWait1=-1,iRetWait2=-1;
	int i=0;
	/*begin ******哲学家线程获取筷子资源进餐-受同步控制*********************/ 
	//根据线程编号选择筷子编号并尝试获取第一个筷子,未成功获取则等待一段时间后重试
	//成功后继续请求下一个新筷子
	for(i=0;(i<5)&&(iRetWait1!=0);i++){
		//获取第一根筷子
		if(iIndex%2==1){
			iRetWait1=sem_timedwait(sem_chops+iIndex,&first_time);
		}
		iRetWait2=sem_timedwait(sem_chops+(iIndex+1)%5,&first_time);
		//设置任务完成标志为1,线程结束
		finish[iIndex]=1;
		//释放筷子资源iIndex
		sem_post(&sem_chops[iIndex]);
		//释放筷子资源
		sem_post(&sem_chops[(iIndex+1)%5]);

	}
	 
	
	
	/****end*****************************************/
    //线程结束时间点:约为700MS	
	return;
}
 

//该线程用于检测哲学家未经同步控制完成任务的数量
int ReporterPhi(void*(*phiFunc)(void*))
{
  int iFinishCount=0;
  pthread_t pids[5]; 
  int arg[5];
  int iRetWait1=-1,iRetWait2=-1,retVal=-1;
  int i=0; 
  gettimeofday(&begintime, NULL);
  //第一次获取筷子资源时间点:100MS
  time_add_ms(&begintime, TIMEOUT_FIRST);
  first_time.tv_sec = begintime.tv_sec;
  first_time.tv_nsec = begintime.tv_usec * 1000;  
  
  //保持获取筷子资源到时间点:300MS
  time_add_ms(&begintime, TIMEOUT_HOLD);
  phi_holdtime.tv_sec = begintime.tv_sec;
  phi_holdtime.tv_nsec = begintime.tv_usec * 1000; 
  
  //哲学家线程结束时间点:500毫秒
  time_add_ms(&begintime, TIMEOUT_PHIEND);
  phi_endtime.tv_sec= begintime.tv_sec;
  phi_endtime.tv_nsec= begintime.tv_usec * 1000; 
  
  //汇报线程完成情况时间点:700MS
  time_add_ms(&begintime, TIME_REPORT);
  report_time.tv_sec = begintime.tv_sec;
  report_time.tv_nsec = begintime.tv_usec * 1000; 
  
  

  sem_init(&sem_stop,0,0);//该信号量初值为0 
  
  //初始化完成数组为0,筷子信号量值为1
  for(i=0;i<5;i++)
  {
	finish[i]=0;
	//设置信量初值为1
	sem_init(sem_chops+i,0,1); 
  }
  
  for(i=0;i<5;i++)
  {
	arg[i]=i;//传给线程的参数值,用来区分线程实体
	//创建消费者线程,pids+i是线程ID的保存地址,arg+i是线程的参数指针 
	pthread_create(pids+i,NULL,phiFunc,(void *)(&arg[i]));  
  } 
  
  //等待哲学家线程结束,但都没有完成任务。
  for(i=0;i<5;i++)
  {
	pthread_join(pids[i],NULL);  //主线程等待生产者线程结束
  }  
  //等待到报告时间点:700MS 
  retVal = sem_timedwait(&sem_stop, &report_time);  
  iFinishCount=0;
  for(i=0;i<5;i++)
  {
	if(finish[i]==1)
	{iFinishCount++;} 
  } 
  return iFinishCount;
}



int main(int argc,char * argv[])
{ 
  int i=0; 
  int phi1=-1,phi2=-1;
  //调用无同步控制的哲学家线程
  phi1=ReporterPhi(Philosopher);
  //调用有同步控制的哲学家线程
  phi2=ReporterPhi(PhilosopherGood); 
  //输出两种情况下完成任务的线程数
  printf("%d,%d",phi1,phi2);
  //销毁信号量资源
  for(i=0;i<5;i++)
  {
	sem_destroy(sem_chops+i); 
  } 
  sem_destroy(&sem_stop); 
  return 0;
}
  • 2
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值