欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

哲学家进餐问题

程序员文章站 2022-04-20 11:47:06
...

问题描述:

问题描述: 5个哲学家围坐在一个圆桌上,每两个哲学家之间都有一只筷子,哲学家平时进行思考,只有当他们饥饿时,才拿起筷子吃饭。规定每个哲学家只能先取其左边筷子,然后取其右边筷子,然后才可以吃饭。

#include<stdio.h>//c语言中主要的函数库 
#include<stdlib.h>//stdlib 头文件里包含了C、C++语言的最常用的系统函数
#include<pthread.h>//线程对应函数库 
#include<iostream>//输入输出流,有输入输出对应的库函数 
#include<unistd.h>//对于类 Unix 系统,unistd.h 中所定义的接口通常都是大量针对系统调用的封装
//是 C 和 C++ 程序设计语言中提供对 POSIX 操作系统 API 的访问功能的头文件的名称。 
#include<semaphore.h>//信号量对应的库函数 
#define N 5    //5位哲学家 
#define LEFT i   //左边筷子 
#define RIGHT (i+1)%N   //右边筷子 
using namespace std;

//信号量机制 
class Semaphore{
   private:
      sem_t sem;
   public:
      Semaphore(int value=1){//这里是5根筷子,五位哲学家竞争,筷子是临界资源。所以每个对象都是 1 
        sem_init(&sem,0,value);
      }
      void P(){
       sem_wait(&sem);//P操作  "--"操作 
      }
      void V(){
        sem_post(&sem);//V操作  "++" 操作 
      }
};

//全局变量 
//信号量机制 
Semaphore mutex[N];//互斥信号量数组 1 1 1 1 1 
//线程 
pthread_t thread[N];//线程数组  5个线程 
int id[N];  //线程标号 
int add=0;//增量  增加到30就面条吃完了
 
void* solve(void*param){
    int i =*((int*)param);// param 是形参,实参是线程 id[N]的地址  , 这里用int*指针指向它,再取值 
    while(true){
       if(add>=30){
          cout<<"哲学家"<<i<<"面条吃完了!!"<<endl;//每个人的面规定是30下 
          break;
       }
       cout<<"哲学家"<<i<<"正在思考"<<endl;//思考不会死锁,只在进餐时有可能死锁 
       if(i%2==0){
          mutex[LEFT].P();
          mutex[RIGHT].P();
          cout<<"哲学家"<<i<<"进餐"<<endl;
          add++;
         // cout<<add<<endl;
          mutex[RIGHT].V();
          mutex[LEFT].V();
       }else{

//*********下面可能会产生死锁,原因是: 如果所有哲学家都同时拿起右边的筷子,大家都因为没能达到自己要求而不肯释放自己的资源
//所以会产生死锁。 
          mutex[RIGHT].P();
          mutex[LEFT].P();
          cout<<"哲学家"<<i<<"进餐"<<endl;
          add++;
          //cout<<add<<endl;
          mutex[LEFT].V();
          mutex[RIGHT].V();
 //      }
       sleep(1); // 让线程休眠的目的是使线程让出CPU的使用权.当线程休眠时,会将CPU资源的使用 
     //单位是毫秒 //交给其他线程,以便能够线程之间的轮换调用.当休眠一定时间后,线程就会苏醒,然后进入准备状态等待执行.
    	}
	}
} 
//创建线程 
void thread_create() {
   int tmp;
   for(int i=0; i<N; i++){//5位哲学家
    	//*************重点 
//    	有四个参数,第一个参数是线程标识符,第二个参数是线程的属性(null是指线程需要手动释放,需要相关函数,如果是其他线程会分离出来会自己释放),
//		第三个参数是处理函数(让线程执行操作),第四个参数是处理函数的形参(类型是 void*) 
      tmp=pthread_create(&thread[i],NULL,solve,&id[i]);//
      
      if(tmp!=0){//pthread_create有返回值 等于0是正常情况,如果错误返回值是其他  
          cout<<"线程"<<i<<"结束"<<endl;//正常的话这里是不执行的 
      }
   }
}
//线程等待 
void thread_wait(){//线程唤醒机制,唤醒处于睡眠中的线程,所以处理函数中的sleep()函数和这里是匹配的 
    for(int i=0; i<N; i++){
       pthread_join(thread[i],NULL);//线程的标识符和线程的属性 
    }
}
int main(){
    for(int i=0; i<N; i++){//5位哲学家装入到数组里面,通过下标来操作 
        id[i]=i;//哲学家编号数组 
    }
    thread_create();//线程创建 
    thread_wait();//线程等待 
    
    return 0;
}

今日分享

运行结果:
哲学家进餐问题

相关标签: 哲学家进餐问