当前位置:文档之家› 用多线程同步方法解决哲学家就餐问题报告

用多线程同步方法解决哲学家就餐问题报告

课程设计报告书课程名称:计算机操作系统题目:用多线程同步方法解决哲学家就餐问题系名:专业班级:姓名:学号:指导教师:2016 年 6 月 24 日武汉华夏理工学院信息工程系课程设计任务书课程名称:操作系统原理课程设计指导教师:班级名称:开课系、教研室:自动化与计算机一、课程设计目的与任务操作系统课程设计是《操作系统原理》课程的后续实践课程,旨在通过一周的实践训练,加深学生对理论课程中操作系统概念,原理和方法的理解,加强学生综合运用操作系统原理、Linux系统、C语言程序设计技术进行实际问题处理的能力,进一步提高学生进行分析问题和解决问题的能力,包含系统分析、系统设计、系统实现和系统测试的能力。

学生将在指导老师的指导下,完成从需求分析,系统设计,编码到测试的全过程。

二、课程设计的内容与基本要求1、课程设计题目用多线程同步方法解决哲学家就餐问题2、课程设计内容本课程设计要求在Linux操作系统,GCC编译环境下开发。

用c/c++语言在Linux操作系统环境下,通过研究Linux的线程机制和信号量实现哲学家就餐问题的并发控制。

为避免死锁,可采用只许4个哲学家入席且桌上有5支筷子的办法。

几把椅子可用连续存储单元。

1 每个哲学家取得一双筷子开始用餐后,即时显示“Dining…”和该哲学家的标识符以及餐桌上有几位哲学家及其所坐的位置。

2 设定共有10个哲学家需用餐。

每位用餐耗时10秒钟以上。

3 多个哲学家须共享操作函数代码。

提示:1 有界缓冲区/连续存储区可用数组实现。

2 编译命令可用:gcc -lpthread -o 目标文件名源文件名3 多线程编程方法参见电子文档。

3、设计报告撰写格式要求:1设计题目与要求 2 设计思想3系统结构 4 数据结构的说明和模块的算法流程图5 使用说明书(即用户手册):内容包含如何登录、退出、读、写等操作说明6 运行结果和结果分析(其中包括实验的检查结果、程序的运行情况)7 自我评价与总结8 附录:程序清单,注意加注释(包括关键字、方法、变量等),在每个模块前加注释;三、课程设计步骤及时间进度和场地安排课程设计集中时间安排:四、课程设计考核及评分标准课程设计考核将综合考虑学生的系统设计方案、运行结果、课程设计报告书的质量、态度、考勤、答辩情况等各因素。

具体评分标准如下:(1)设计方案正确,具有可行性、创新性; 30分(2)系统开发效果较好; 20分(3)设计报告规范、课程设计报告质量高、参考文献充分 20分(4)课程设计答辩时,问题回答正确; 20分(5)态度认真、刻苦钻研、遵守纪律; 10分按上述五项分别记分后求和,总分按五级制记载最后成绩。

优秀(100~90分),良好(80~89分),中等(70~79分),及格(60~69分),不及格(0~59分)一、设计题目:用多线程同步方法解决哲学家就餐问题二、设计思想:1、为每个哲学家产生一个线程,设计正确的同步算法2、每个哲学家取得一双筷子开始用餐后,即时显示“Dining…”和该哲学家的自定义标识符以及餐桌上所有几位哲学家标识符及其所坐的位置。

3、设定共有10个哲学家需用餐。

每位用餐耗时10秒钟以上。

4、多个哲学家须共享操作函数代码。

三、系统结构四、主要数据结构的说明和模块的算法流程图:1、创建函数pthread_create声明如下:#include <pthread.h>Int pthread_create(pthread_t *thread, const pthread_attr_t *attr,void*(*start_routine) (void *), void *arg);2、等待其它线程结束函数pthread_join声明如下:#include <pthread.h>int pthread_join(pthread_t thread, void **retval);3、信号量的数据类型为结构sem_t,它本质上是一个长整型的数。

初始化信号量函数sem_init声明如下:#include <semaphore.h>sem_init (sem_t *sem, int pshared, unsigned int value);4、增加信号量值函数sem_post声明如下:#include <semaphore.h>int sem_post(sem_t *sem);5、减少信号量值函数sem_wait声明如下#include <semaphore.h>int sem_wait(sem_t * sem);主要数据结构声明:1、#define NUMBERS 10 //将哲学家人数NUMBERS定义为102、sem_t chopstics[NUMBERS] //定义5只筷子的互斥信号量chopstics3、sem_t room //定义避免死锁的同步信号量room线程共享函数伪代码:void *Share(int i){think();p(room); //请求入席进餐p(chopstick[setnumber]); //请求左手边的筷子p(chopstick[setnumber+1]); //请求右手边的筷子eat();v (chopstick[setnumber]); //释放左手边的筷子v(chopstick[setnumber+1])); //释放右手边的筷子v(room); //退出席位释放信号量chairs}五、使用说明:打开虚拟机,进入linux系统。

应用程序—终端—输入gcc –lpthread –o a.a.c—编码成功后,输入./a ,得到所需结果。

六、运行结果和结果分析:如图1、2所示:图1图2[syh@localhost ~]$ gcc -lpthread -o a a.c [syh@localhost ~]$ ./a哲学家1坐上了位置1哲学家1拿到左侧筷子1哲学家1拿到右侧筷子2哲学家1坐在1椅子上吃饭dining……***************哲学家1坐在椅子1上————————————哲学家2坐上了位置2哲学家3坐上了位置3哲学家3拿到左侧筷子3哲学家3拿到右侧筷子4哲学家3坐在3椅子上吃饭dining……***************哲学家1坐在椅子1上哲学家2坐在椅子2上哲学家3坐在椅子3上————————————哲学家4坐上了位置4哲学家1吃饱了放下筷子1和2哲学家1离开了位置1走到一边画圈圈哲学家3吃饱了放下筷子3和4哲学家3离开了位置3走到一边画圈圈哲学家2拿到左侧筷子2哲学家2拿到右侧筷子3哲学家2坐在2椅子上吃饭dining……***************哲学家2坐在椅子2上————————————哲学家5坐上了位置1哲学家5拿到左侧筷子1哲学家4拿到左侧筷子4哲学家4拿到右侧筷子5哲学家4坐在4椅子上吃饭dining……***************哲学家5坐在椅子1上哲学家2坐在椅子2上————————————哲学家2吃饱了放下筷子2和3哲学家4吃饱了放下筷子4和5哲学家4离开了位置4走到一边画圈圈哲学家5拿到右侧筷子2哲学家5坐在1椅子上吃饭dining……***************哲学家5坐在椅子1上哲学家2坐在椅子2上————————————哲学家6坐上了位置3哲学家6拿到左侧筷子3哲学家6拿到右侧筷子4哲学家6坐在3椅子上吃饭dining……***************哲学家5坐在椅子1上哲学家2坐在椅子2上哲学家6坐在椅子3上————————————哲学家2离开了位置2走到一边画圈圈哲学家8坐上了位置2哲学家9坐上了位置4哲学家5吃饱了放下筷子1和2哲学家5离开了位置1走到一边画圈圈哲学家6吃饱了放下筷子3和4哲学家6离开了位置3走到一边画圈圈哲学家8拿到左侧筷子2哲学家8拿到右侧筷子3哲学家8坐在2椅子上吃饭dining……***************哲学家8坐在椅子2上————————————哲学家7坐上了位置1哲学家7拿到左侧筷子1哲学家9拿到左侧筷子4哲学家9拿到右侧筷子5哲学家9坐在4椅子上吃饭dining……***************哲学家7坐在椅子1上哲学家8坐在椅子2上————————————哲学家8吃饱了放下筷子2和3哲学家7拿到右侧筷子2哲学家7坐在1椅子上吃饭dining……***************哲学家7坐在椅子1上哲学家8坐在椅子2上————————————哲学家9吃饱了放下筷子4和5哲学家9离开了位置4走到一边画圈圈哲学家8离开了位置2走到一边画圈圈哲学家10坐上了位置3哲学家10拿到左侧筷子3哲学家10拿到右侧筷子4哲学家10坐在3椅子上吃饭dining……***************哲学家7坐在椅子1上哲学家10坐在椅子3上————————————哲学家7吃饱了放下筷子1和2哲学家7离开了位置1走到一边画圈圈哲学家10吃饱了放下筷子3和4哲学家10离开了位置3走到一边画圈圈七、测试过程及结果分析:各个哲学家(线程)完全独立自主运作,达到了预期的目标,拿筷子自然无冲突,吃饭也能正常运行,全程序没有一个哲学家饿死(线程不执行),或者是有哲学家在座位上却吃不到饭(死锁)的问题。

所有的哲学家都可以去画圈圈。

八、心得体会:虽然这次课程设计用了一星期,但是通过查阅资料,还是有了很大的收获,,使我对操作系统的基本知识有了进一步的提高,并在实践中对各种概念有了进一步的深化。

初看别人的编程,根本就不知道写的是什么。

只知道不停的运行,却一直得不到结果,坐着干着急。

后来,慢慢地从一点一滴的学习中,能够将程序读懂了,这就是最大的进步。

通过这次课程设计,我确实学到了很多东西,这些学到的东西可以使我受益终生。

除了知识技术上的东西,我更锻炼了自己的快速学习能力。

总的来说,这次的课程设计的收获比较大,对LINUX的运用以及编程都更进了一步。

一个看似小程序,却包含了很多辛劳,没有扎实的理论基础和熟练地操作是很难在短时间内完成作品的。

九、附录:#include <stdio.h>#include <unistd.h>#include <pthread.h>#include <semaphore.h>#define NUMBERS 10//设置哲学家数目sem_t chopstics[5];//设置筷子数目sem_t room; //设置房屋信号灯sem_t mutex;//设置互斥信号灯sem_t yourenmutex;//设置有人互斥信号灯int youren[5]={0,0,0,0,0};//设置是人变量int chairs[4]={1,2,3,4};//设置椅子int i,j;//设置2循环用变量void *Share(int threadid);//定义哲学家函数//主函数int main(){int error;//设定错误变量pthread_t threads[NUMBERS];//设置线程数for(i=0;i<5;i++)//循环设置筷子信号灯{sem_init(&chopstics[i],0,1);}sem_init(&room,0,4);//设置房间信号灯sem_init(&mutex,0,1);//设置互斥信号灯for(i=1;i<NUMBERS+1;i++)//建立十个哲学家线程{error = pthread_create(&threads[i],NULL,(void *)Share,(void *)i); if(error)//判断是否产生哲学家{printf("\nERROR: 哲学家没有被创建\n");}}for(i=1;i<NUMBERS+1;i++)//启动十个哲学家线程{pthread_join(threads[i],NULL);}}//哲学家函数void *Share(int threadid){int i = threadid;//读取哲学家编号int setnumber=1;//设置座位量sem_wait(&room);//room信号-1for(setnumber=1;setnumber<=4;setnumber++)//检测哪个位置空出来{if(youren[setnumber]==0){youren[setnumber]=i; //让哲学家去坐座位,并修改有人编号为哲学家编号printf("哲学家%d坐上了椅子%d\n",i,setnumber);sem_post(&yourenmutex);//解除有人互斥break;}}sem_wait(&chopstics[setnumber]);//拿起左边筷子信号灯printf("哲学家%d拿到左侧筷子%d\n",i,setnumber);sem_wait(&chopstics[setnumber+1]);//拿起右边筷子信号灯printf("哲学家%d拿到右侧筷子%d\n",i,setnumber+1);sem_wait(&mutex);//互斥printf("哲学家%d坐在%d椅子上吃饭\n",i,chairs[setnumber-1]);printf("dining……\n");printf("***************\n");for(j=0;j<4;j++){if(youren[j]!=0)printf("哲学家%d坐在椅子%d上\n",youren[j],chairs[j-1]);}printf("————————————\n");sem_post(&mutex);//解除互斥sleep(1);//吃十秒sem_post(&chopstics[setnumber]);//放下左边筷子信号灯sem_post(&chopstics[setnumber+1]);//放下右边筷子信号灯printf("哲学家%d吃饱了放下筷子%d和%d\n",i,setnumber,setnumber+1); sem_wait(&yourenmutex);//有人互斥youren[setnumber]=0;printf("\n哲学家%d离开了椅子%d走到一边画圈圈\n\n",i,setnumber); sem_post(&yourenmutex);//解除有人互斥sem_post(&room);//room信号灯+1}。

相关主题