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

合集下载

操作系统课程设计利用多线程和信号量解决哲学家进餐问题java实现

操作系统课程设计利用多线程和信号量解决哲学家进餐问题java实现

操作系统课程设计利用多线程和信号量解决哲学家进餐问题j a v a实现IMB standardization office【IMB 5AB- IMBK 08- IMB 2C】操作系统课程设计课程设计报告课题:利用信号量和多线程机制实现“哲学家进餐”问题所在学院:信息工程学院班级:计科1201学号:4姓名:魏祥指导教师:徐向英2015年1月 1日目录一、课程设计目标 (3)二、课题内容 (3)三、设计思路 (3)四、源代码 (5)五、运行与测试 (9)六、心得体会 (10)一、课程设计目标学习多线程编程,使用线程的同步机制实现“哲学家进餐”问题。

具体要求:1.创建POSIX线程,实现多线程的并发执行,验证多线程共享进程资源的特性。

2.使用互斥量和条件变量,或使用信号量实现线程的同步互斥。

3.验证“哲学家进餐”问题中的死锁情况,并加以解决。

二、课题内容哲学家进餐问题由Dijkstra提出,问题描述有五个哲学家共用一张圆桌,分别坐在周围的五张椅子上,在圆桌上有五个碗和五支筷子,他们的生活方式是交替地进行思考和进餐。

平时,一个哲学家进行思考,饥饿时便试图取用其左右最靠近他的筷子,只有在他拿到两只筷子时才能进餐。

进餐完毕,放下筷子继续思考。

本次课题要求使用多线程和信号量解决哲学家进餐问题。

并演示产生死锁的情况。

三、设计思路经分析可知,放在桌子上的筷子是临界资源,在一段时间内只允许以为哲学家使用。

为了实现对筷子的互斥,可以用一个信号量表示一只筷子,由着五个信号量构成信号量数组。

当哲学家饥饿时总是先去拿左筷子,成功后在拿右筷子。

当五位哲学家同时拿起左筷子,这是每位哲学家都没有右筷子可以拿,就会造成死锁。

思路1:利用记录型信号量设置值为4的记录型信号量,至多只允许四位哲学家同时去拿左筷子().acquire()),只有拿到左筷子,才能继续拿右筷子().acquire())。

拿到两双筷子之后便可以用餐,用餐完毕,先放下左筷子().release()),再放下右筷子().release())。

操作系统课程设计——哲学家进餐问题

操作系统课程设计——哲学家进餐问题

操作系统课程设计——哲学家进餐问题1000字哲学家进餐问题是一个经典的多线程同步问题,在操作系统中有着广泛的应用。

因此,在操作系统课程设计中,探究哲学家进餐问题是一件非常有意义的事情。

哲学家进餐问题的场景是:五个哲学家围坐在一张圆桌前,每个哲学家的左右两侧有一只筷子,他们需要利用这两只筷子才能进餐。

每个哲学家有两种状态:思考和进餐。

当一个哲学家处于进餐状态时,他需要同时获取他左右两侧的筷子,进餐结束后,他会释放这两只筷子,进入思考状态。

在这个场景中,如果所有的哲学家都同时想要进餐,那么就可能会出现死锁情况,即所有的哲学家都拿到了左手边的筷子,但都无法拿到右手边的筷子,导致无法进餐。

因此,需要在代码中实现同步互斥机制,避免死锁的发生。

本课程设计中,我使用了Java语言来实现哲学家进餐问题。

在代码实现中,首先定义了哲学家、筷子、餐桌等对象,然后使用线程来模拟哲学家的思考和进餐过程。

为了避免死锁,我使用了Chandy/Misra算法,即每个哲学家先尝试去取左手边的筷子,如果取不到就不再继续等待,而是重新回到思考状态,等待下一个机会。

同时,当一个哲学家取到了左手边的筷子之后,如果发现右手边的筷子已被占用,他就会释放左手边的筷子,重新回到思考状态,等待下一个机会。

在实现过程中,我还使用了信号量机制,保证了线程间的同步互斥。

每个筷子都是一个二元信号量,初始为1,表示可用。

当一个哲学家拿起筷子时,他会将对应的信号量减1,表示不可用。

当哲学家用完筷子之后,会将对应的信号量加1,表示可用。

通过这种方式,实现了对筷子的访问同步。

最后,我对代码进行了测试,模拟了多位哲学家同时进行进餐的过程。

在测试中,我发现哲学家进餐的速度受到筷子的数量和哲学家思考进餐比例的影响。

当筷子数量少于哲学家数量时,容易出现死锁;当哲学家思考和进餐的时间相当时,程序的运行情况比较稳定。

总的来说,本课程设计实现了哲学家进餐问题,通过学习该问题,我更深入地理解了同步互斥机制的重要性,并学会了如何使用信号量来实现同步互斥。

哲学家进餐问题

哲学家进餐问题

哲学家进餐问题2007/05/16 12:36 P.M./********************philosophers.cpp哲学家进餐问题在多线程中如何避免死锁。

问题描述:有五位哲学家围绕着餐桌坐,每一位哲学家要么思考要么等待,要么吃饭。

为了吃饭,哲学家必须拿起两双筷子(分别放于左右两端)不幸的是,筷子的数量和哲学家相等,所以每只筷子必须由两位哲学家共享下面是一种有问题的解法,因为在某个时刻,五个哲学家同时拿起五根左手边的筷子,则它们会在同一时候对待右手边的筷子,这样会陷入死锁,但是我测试了,这样的几率并不高经过几个小时,还没有出现。

但是我们可以肯定,理论上是肯定会出现死锁的,我们不能老是靠运气办事,怎么解决这个问题呢留给下一步的学习吧要编译此文件请用多线程版的c++库********************/#include <windows.h>#include <iostream>#include <process.h>#include <cstdlib>#include <ctime>using namespace std;unsigned int __stdcall philosopher(void *);void thinking(int);void eating(int);void wait_to_eat(int);void outline(int ,const char *);//全局变量CRITICAL_SECTION crout;//这个变量用来保证输出时不会竞争CRITICAL_SECTION fork[5];//定义五个临界变量,代表五更筷子int main(int argc,char *argv[]){void * hthread[5];int i;unsigned int threadid[5];int arg[5];int count = 5;unsigned long retval;InitializeCriticalSection(&crout);//初始化临界变量for(i=0;i<5;i++){InitializeCriticalSection(fork + i);}//创建五个哲学家for(i = 0; i<5;i++){arg[i] = i;hthread[i] = (void *)_beginthreadex(NULL,0,philosopher,(void *)(arg + i),0,threadid+i);if((int)hthread[i] == -1)//如果线程创建失败返回-1{cerr << "error while create thread " << i <<endl;cerr << "error code : "<< GetLastError() <<endl;}}//等待所有线程结束retval = WaitForMultipleObjects(5,hthread,true,INFINITE);//等待多个线程if(retval == WAIT_FAILED){cerr<< "wait error,error code: "<<GetLastError()<<endl;}for(i = 0; i<5;i++){if(CloseHandle(hthread[i]) == false)//关闭句柄{cerr << "error while close thread " <<i<<endl;cerr << "error code: "<<GetLastError()<<endl;}}return 0;}/*******************哲学家的行为吃饭,等待,思考*******************/unsigned int __stdcall philosopher(void *k){int n = ((int *)k)[0];outline(n," is in!");srand(time(NULL));while(true){thinking(n);wait_to_eat(n);eating(n);}outline(n," is out!");return n;}/*************思考随机一段时间*************/void thinking(int k){outline(k," is thinking...");Sleep((rand()%1000) *5);}/*************吃饭随机一段时间*************/void eating(int k){outline(k," is eating...");Sleep((rand()%1000) *5);LeaveCriticalSection(fork + (k+1)%5);//放下右边的筷子//outline(k," give left");LeaveCriticalSection(fork + k);//放下左边的筷子//outline(k," give right");}/***************等待吃饭需要同时获得他两边的筷子***************/void wait_to_eat(int k){outline(k," is waiting...");EnterCriticalSection(fork + k);//获得左边的筷子//outline(k," take left");EnterCriticalSection(fork + (k + 1)%5);//获得右边的筷子//outline(k," take right");}/********************//没有竞争条件的输出函数********************/void outline(int who,const char *str){EnterCriticalSection(&crout);cout<<"process "<<who<<str<<endl;LeaveCriticalSection(&crout);}/********************philosophers.cpp哲学家进餐问题在多线程中如何避免死锁。

操作系统课程设计利用多线程和信号量解决哲学家进餐问题java实现

操作系统课程设计利用多线程和信号量解决哲学家进餐问题java实现

操作系统课程设计课程设计报告课题:利用信号量和多线程机制实现“哲学家进餐”问题所在学院:信息工程学院班级:计科1201学号:121404114姓名:魏祥指导教师:徐向英2015年1月1日目录一、课程设计目标 (3)二、课题内容 (3)三、设计思路 (3)四、源代码 (5)五、运行与测试 (9)六、心得体会 (10)一、课程设计目标学习多线程编程,使用线程的同步机制实现“哲学家进餐”问题。

具体要求:1.创建POSIX线程,实现多线程的并发执行,验证多线程共享进程资源的特性。

2.使用互斥量和条件变量,或使用信号量实现线程的同步互斥。

3. 验证“ 哲学家进餐”问题中的死锁情况,并加以解决。

二、课题内容哲学家进餐问题由Dijkstra提出,问题描述有五个哲学家共用一张圆桌,分别坐在周围的五张椅子上,在圆桌上有五个碗和五支筷子,他们的生活方式是交替地进行思考和进餐。

平时,一个哲学家进行思考,饥饿时便试图取用其左右最靠近他的筷子,只有在他拿到两只筷子时才能进餐。

进餐完毕,放下筷子继续思考。

本次课题要求使用多线程和信号量解决哲学家进餐问题。

并演示产生死锁的情况。

三、设计思路经分析可知,放在桌子上的筷子是临界资源,在一段时间内只允许以为哲学家使用。

为了实现对筷子的互斥,可以用一个信号量表示一只筷子,由着五个信号量构成信号量数组。

当哲学家饥饿时总是先去拿左筷子,成功后在拿右筷子。

当五位哲学家同时拿起左筷子,这是每位哲学家都没有右筷子可以拿,就会造成死锁。

思路1:利用记录型信号量设置值为4的记录型信号量,至多只允许四位哲学家同时去拿左筷子(leftStick.getSema().acquire()),只有拿到左筷子,才能继续拿右筷子(rightStick.getSema().acquire())。

拿到两双筷子之后便可以用餐,用餐完毕,先放下左筷子(leftStick.getSema().release()),再放下右筷子(rightStick.getSema().release())。

操作系统哲学家就餐问题实验报告

操作系统哲学家就餐问题实验报告

include <>include <>include <string>include <iostream>include <>using namespace std;bool tools5; //全局变量,用餐工具CRITICAL_SECTION cs; //信号量, 在线程中使用,临界区class Philosopher{private:int number;int status; /标记当前哲学家的状态,0表示正在等待即处于饥饿状态,1表示得到两支筷子正在吃饭,2表示正在思考/ public:Philosopherint num=0: status2, numbernum { }const int find{return number;}const int getinfo{ return status; }void Change ; //状态改变函数void dead_lock;};/////////void Philosopher::dead_lock{EnterCriticalSection &cs ; //进入临界区 string s;ifstatus==1{toolsnumber%5=true;// toolsnumber-1%5=true;status=2;}else ifstatus==2{status=0;//toolsnumber-1%5=false;//toolsnumber-1%5=true;}else ifstatus==0{toolsnumber%5=false;toolsnumber-1%5=false;status=1;}LeaveCriticalSection &cs ;// cout<<"";}/////////void Philosopher::Change{EnterCriticalSection &cs ; //进入临界区 ifstatus==1 //正在进餐{toolsnumber%5=true; //放下左手工具 toolsnumber-1%5=true; //放下右手工具 status=2; //改变状态为思考}else ifstatus==2 //思考中{status=0; //改变状态为等待}else ifstatus==0 //等待中{iftoolsnumber%5&&toolsnumber-1%5 //左右手两边工具均为空闲状态{toolsnumber%5=false; //拿起左手工具toolsnumber-1%5=false; //拿起右手工具status=1;}}LeaveCriticalSection &cs ;}string printPhilosopher pA{//pA->Change;int i=pA->getinfo;string str;ifi==0str="等待";else ifi==1str="就餐";else str="思考";return str;}string toolstatusbool a{string state;ifa==truestate="闲";ifa==falsestate="用";return state;}int main{char con='y'; //判断是否继续// con = 'n';forint i=0;i<5;i++toolsi=true; //筷子都未使用,初始化Philosopher P11,P22,P33,P44,P55;InitializeCriticalSection &cs ; //初始化初始化临界区cout<<"-----------------------状态说明示意图:-----------------------"<<endl;cout<<" "<<"哲学家1号的状态"<<" "<<endl;cout<<" 筷子0的状态"<<" "<<"筷子1的状态"<<endl;cout<<"哲学家5号的状态"<<" "<<"哲学家2号的状态"<<endl;cout<<" 筷子4的状态"<<" "<<"筷子2的状态"<<endl;cout<<" 哲学家4号的状态"<<" "<<"哲学家3号的状态"<<endl;cout<<" "<<"筷子3的状态"<<endl;//cout<<" "<<"哲学家3号的状态"<<" "<<endl;cout<<"筷子的状态,用表示使用中,闲表示空闲中;"<<endl;cout<<"--------------------------------------------------------------"<<endl ;//cout<<"哲学家们开始生活:"<<endl;//cout<<"当前状态:";cout<<endl;//cin>>con;whilecon=='y'{; ; ; ; ;cout<<"当前状态为:"<<endl;cout<<" "<<<<print&P1<<" "<<endl;cout<<" "<<toolstatustools0<<" "<<toolstatustools1<<endl;cout<<" "<<<<print&P5<<" "<<<<print&P2<<endl;cout<<" "<<toolstatustools4<<" "<<toolstatustools2<<endl;cout<<" "<<<<print&P4<<" "<<<<print&P3<<endl;cout<<" "<<toolstatustools3<<endl;cout<<"--------------------------"<<endl;cout<<"若要继续下一状态,输入y;输入n进入死锁;输入其他,结束程序:";cin>>con;Sleep20;}whilecon=='n'{;; ; ; ;cout<<"死锁情况"<<endl;cout<<" "<<<<print&P1<<" "<<endl;cout<<" "<<toolstatustools0<<" "<<toolstatustools1<<endl;cout<<" "<<<<print&P5<<" "<<<<print&P2<<endl;cout<<" "<<toolstatustools4<<" "<<toolstatustools2<<endl;cout<<" "<<<<print&P4<<" "<<<<print&P3<<endl;cout<<" "<<toolstatustools3<<endl;cout<<"--------------------------"<<endl;cout<<"输入n继续;输入其他,结束程序:";cin>>con;Sleep20;}DeleteCriticalSection &cs ; //退出资源区return 0;}。

利用AND信号量机制解决哲学家进餐问题

利用AND信号量机制解决哲学家进餐问题

利⽤AND信号量机制解决哲学家进餐问题哲学家就餐问题是1965年由Dijkstra提出的⼀种线程同步的问题。

问题描述:⼀圆桌前坐着5位哲学家,两个⼈中间有⼀只筷⼦,桌⼦中央有⾯条。

哲学家思考问题,当饿了的时候拿起左右两只筷⼦吃饭,必须拿到两只筷⼦才能吃饭。

上述问题会产⽣死锁的情况,当5个哲学家都拿起⾃⼰右⼿边的筷⼦,准备拿左⼿边的筷⼦时产⽣死锁现象。

解决办法: 1、添加⼀个服务⽣,只有当经过服务⽣同意之后才能拿筷⼦,服务⽣负责避免死锁发⽣。

2、每个哲学家必须确定⾃⼰左右⼿的筷⼦都可⽤的时候,才能同时拿起两只筷⼦进餐,吃完之后同时放下两只筷⼦。

3、规定每个哲学家拿筷⼦时必须拿序号⼩的那只,这样最后⼀位未拿到筷⼦的哲学家只剩下序号⼤的那只筷⼦,不能拿起,剩下的这只筷⼦就可以被其他哲学家使⽤,避免了死锁。

这种情况不能很好的利⽤资源。

package操作系统;class Philosopher extends Thread {private String name;private Fork fork;public Philosopher(String name, Fork fork) {super(); = name;this.fork = fork;}@Overridepublic void run() {thinking();fork.takeFork();eating();fork.putFork();}void eating() {System.out.println("I'm eating " + name);try {sleep(1000);} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}}void thinking() {System.out.println("I'm thinking" + name);try {sleep(1000);} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}}}class Fork {boolean[] used = { false, false, false, false, false };synchronized void takeFork() {String threadName = Thread.currentThread().getName();String name = threadName.substring(threadName.length()-1, threadName.length());int i = Integer.parseInt(name);while (used[i] || used[(i + 1) % 5]) {try {wait();} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}}used[i] = true;used[(i + 1) % 5] = true;}synchronized void putFork() {String threadName = Thread.currentThread().getName();String name = threadName.substring(threadName.length()-1, threadName.length());int i = Integer.parseInt(name);used[i] = false;used[(i + 1) % 5] = false;notifyAll();}}public class哲学家就餐问题 {public static void main(String[] args) {Fork fork = new Fork();new Philosopher("1", fork).start();new Philosopher("2", fork).start();;new Philosopher("3", fork).start();;new Philosopher("4", fork).start();;new Philosopher("5", fork).start();;}}执⾏结果I'm thinking1I'm thinking3I'm thinking2I'm thinking4I'm thinking5I'm eating 1I'm eating 3I'm eating 5I'm eating 2I'm eating 4。

操作系统实验报告哲学家就餐

操作系统实验报告哲学家就餐

操作系统实验报告哲学家就餐一、实验目的:通过模拟哲学家就餐问题,了解并掌握操作系统中的进程同步机制,以及解决进程间资源竞争所引发的死锁问题。

二、实验介绍:哲学家就餐问题是由荷兰计算机科学家伊克斯特拉(Dijkstra)于1965年首次提出的。

其问题描述如下:五位哲学家坐在一张圆桌子周围,每个哲学家面前有一碗饭和一根筷子。

哲学家的生活方式是交替地进行思考和进食。

当一个哲学家思考时,他不需要使用他的两个筷子;当一个哲学家想吃饭时,他需要同时获取他的左右两个筷子,并在获取到筷子后才能开始进食。

问题的关键是如何解决哲学家间的筷子竞争问题,以及避免死锁的发生。

三、实验设计:1.并发思路每个哲学家作为一个进程,在进行思考和进食这两个操作之前,需要获取他的两个筷子。

接下来考虑进程同步的两个关键点:-互斥:保证每个筷子同时只能被一个哲学家使用,避免资源竞争问题。

-死锁避免:通过限制只允许至多四位哲学家同时持有筷子,从而避免死锁发生。

2.进程同步机制- 互斥:使用Semaphore实现互斥,每个筷子都是一个Semaphore,初始值为1-死锁避免:引入一个全局计数器,记录当前持有筷子的哲学家数量,每次哲学家想要获取筷子时,先检查该计数器,仅当计数器小于4时才会获取筷子。

四、实验步骤:1.创建5个哲学家进程和5个筷子线程。

2.每个哲学家的线程循环执行思考和进食操作。

3.在进食之前,哲学家需要获取两个筷子,获取筷子的顺序按照哲学家编号进行,每个哲学家先获取自己的左边筷子,再获取自己的右边筷子。

4.进行进食操作后,哲学家释放两个筷子。

5.循环执行步骤3和步骤4,直到实验结束。

五、实验结果:通过观察实验结果,可以看到哲学家的思考和进食操作交替进行,并且避免了死锁的发生。

六、实验总结:通过本次实验,我了解了操作系统中的进程同步机制,并学会了如何解决资源竞争和死锁问题。

在本实验中,我使用了Semaphore和全局计数器实现了互斥和死锁避免,从而成功模拟了哲学家就餐问题。

java解哲学家就餐问题

java解哲学家就餐问题

java解哲学家就餐问题哲学家进餐问题是一个多线程运用的经典例子,涉及到线程同步/互斥,临界区访问问题以及一个避免死锁的解决方法。

有五个哲学家绕着圆桌坐,每个哲学家面前有一盘面,两人之哲学家进餐问题是一个多线程运用的经典例子,涉及到线程同步/互斥,临界区访问问题以及一个避免死锁的解决方法。

有五个哲学家绕着圆桌坐,每个哲学家面前有一盘面,两人之间有一支筷子,这样每个哲学家左右各有一支筷子。

哲学家有2个状态,思考或者拿起筷子吃饭。

如果哲学家拿到一只筷子,不能吃饭,直到拿到2只才能吃饭,并且一次只能拿起身边的一支筷子。

一旦拿起便不会放下筷子直到把饭吃完,此时才把这双筷子放回原处。

如果,很不幸地,每个哲学家拿起他或她左边的筷子,那么就没有人可以吃到饭了。

这就会造成死锁了。

这是需要坚决杜绝的,正如操作系统的死锁问题。

代码如下:import java.util.Random;public class DiningPhils{public static void main(String[] args){int n = 10;if( n < 1){System.err.println( "DiningPils <# of philosophers>" );System.exit(-1);}DiningPhils self = new DiningPhils();self.init(n);}public int getCount(){return n;}public void setChopstick( int i, boolean v){chops[ i ] = v;}public boolean getChopstick( int i ){return chops[i];}private void init( final int N){r = new Random();n = ( N < 0 || N > maxPhils ) ? maxPhils : N;chops = new boolean[n];phils = new Philosopher[n];initPhils();dumpStatus();}private void initPhils(){for( int i = 0; i< n; i++ ){phils[i] = new Philosopher( this, i );phils[i].setTimeSlice( generateTimeSlice());phils[i].setPriority( Thread.NORM_PRIORITY - 1);/**哲学家进程降低一级,使所有哲学家进程*全部初始化完毕前不会有哲学家进程抢占主线程*/}while( moreToStart() ){int i = Math.abs( r.nextInt()) % n;if( !phils[i].isAlive()){System.out.println( " ### Philosopher " +String.valueOf( i ) + " started.");phils[i].start();}}System.out.println( "\nPhilosophers Chopsticks" + "\n(1 = eating, 0 = thinking) (1 = taken, 0 = free)"); }public int generateTimeSlice(){int ts = Math.abs(r.nextInt()) % (maxEat + 1);if( ts == 0 )ts = minEat;return ts;}public void dumpStatus(){for( int i = 0; i < n; i++)System.out.print(phils[i].getEat() ? 1 : 0);for( int i = n; i < maxPhils + 4; i++ )System.out.print(" ");for( int i = 0; i < n; i++)System.out.print(chops[i]? 1:0);System.out.println();}private boolean moreToStart(){for( int i = 0; i < phils.length; i++ ){if( !phils[i].isAlive())return true;}return false;}private int n;private Philosopher[] phils;private boolean[] chops;private Random r;private static final int maxPhils = 24; //最多哲学家数 private static final int maxEat = 4; //最多进餐时间 private static final int minEat = 1; //最少进餐时间}class Philosopher extends Thread{public Philosopher( DiningPhils HOST , int i ){host = HOST;index = i;}public void setTimeSlice( int TS ){ts = TS;}public void setLeftChopstick( boolean flag ){host.setChopstick(index, flag);}public void setRightChopstick( boolean flag ){host.setChopstick((index + 1)% host.getCount() , flag);}private void releaseChopsticks(){setLeftChopstick(false);setRightChopstick(false);}public boolean chopsticksFree(){return !host.getChopstick(index) &&!host.getChopstick((index+1)%host.getCount());}public void run(){while(true){grabChopsticks();eat();think();}}private synchronized void grabChopsticks() /**临界区函数,确保哲学家在没有筷子或筷子不够时思考,满足条件后才就餐*/{while( !chopsticksFree()){try{wait();}catch( InterruptedException e){}}takeChopsticks();notifyAll();}private void takeChopsticks(){setLeftChopstick( true );setRightChopstick( true );setEat(true);host.dumpStatus();}private void eat(){pause();setEat( false );releaseChopsticks();}private void think(){pause();}private void pause(){setTimeSlice( host.generateTimeSlice());try{sleep(ts*1000);}catch( InterruptedException e){}}private void setEat(boolean v){isEating = v;}public boolean getEat(){return isEating;}private DiningPhils host;private boolean isEating;private int index;private int ts;}原文出处:中软卓越 。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

课程设计报告书课程名称:计算机操作系统题目:用多线程同步方法解决哲学家就餐问题系名:专业班级:姓名:学号:指导教师: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}。

相关文档
最新文档