哲学家进餐问题
程序员文章站
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;
}
运行结果:
推荐阅读
-
Android 使用volley过程中遇到的问题解决办法
-
Android侧滑菜单和轮播图之滑动冲突问题
-
完美解决PJ的Cookies保存时限问题!可选择记录登陆时长!
-
Android的App启动时白屏的问题解决办法
-
解决Android使用Handler造成内存泄露问题
-
jQuery事件多次绑定与解绑问题实例分析
-
在arcgis使用python脚本进行字段计算时是如何解决中文问题的
-
python学习笔记之调用eval函数出现invalid syntax错误问题
-
Android studio 3.0上进行多渠道打包遇到的问题小结(超简洁版)
-
Mac Android Studio 3.0 Terminal 中文乱码问题处理