死锁的检测与解除C语言代码
- 格式:docx
- 大小:236.56 KB
- 文档页数:8
如何进行编程中的死锁检测和解决方案在多线程编程中,死锁是一种常见而又棘手的问题。
当两个或多个线程彼此等待对方释放资源,而导致所有线程无法继续执行时,就发生了死锁。
死锁不仅会导致程序的崩溃,还会耗尽系统资源,导致性能下降。
本文将介绍编程中的死锁检测和解决方案。
一、死锁的原因和特征死锁产生的原因通常有以下几个方面:1. 互斥条件:一个资源同时只能被一个线程占用。
2. 请求和保持条件:一个线程在获取一些资源的同时保持对已有资源的请求。
3. 不可剥夺条件:已经获得的资源在未使用完之前不能被其他线程剥夺。
4. 循环等待条件:存在一个线程资源的循环链。
死锁的特征主要包括:1. 互斥:至少有一个资源被一个线程排他性地使用,即不能同时被其他线程使用。
2. 占有并等待:至少有一个线程在等待其他线程占有的资源。
3. 不可剥夺:至少有一个资源不能被其他线程抢占。
4. 循环等待:存在一个线程-资源的循环链。
二、死锁检测方法在编程中,检测死锁的方法有以下几种:1. 鸵鸟算法:将死锁问题无视,期望问题不会发生。
但这种方法是不可靠的,因为死锁一旦发生,将会导致程序挂起或崩溃。
2. 静态分析:通过对程序代码进行静态代码分析,找出可能导致死锁的代码。
但这种方法通常需要大量的时间和精力,且不够准确。
3. 动态检测:通过运行时监控线程的状态和资源的使用情况,检测是否存在死锁。
常用的方法包括资源分配图算法和银行家算法。
三、死锁解决方案当发现死锁后,需要采取相应的解决方案来解决问题。
以下是几种常用的死锁解决方案:1. 预防死锁:通过破坏死锁产生的四个条件之一来预防死锁。
例如,避免循环等待,确保资源有序分配等。
这需要在设计和编写代码的过程中就进行考虑,以尽量避免死锁问题的发生。
2. 避免死锁:在程序运行时,控制资源的申请和分配,避免出现死锁的情况。
常用的算法有安全序列算法和银行家算法。
这些算法可以根据系统的资源情况来动态地分配资源,以确保不会发生死锁。
死锁检测/// <summary>///死锁检测解除/// </summary>private void Check(){bool possible = true;ArrayList ArrLock = new ArrayList(); for(int i=0;i<Claim.Length;i++){//用于存放死锁进程索引号//当前每类资源可用的数量ArrLock.Add(i);}bool[] finish = { true, true, true, true, true }; Struction Currentaviail = new Struction();Currentaviail.P1 = Available.P1;Currentaviail.P2 = Available.P2;Currentaviail.P3 = Available.P3;for (int i = 0; i < Allocation.Length; i++){if (Allocation[i].P1 == 0 && Allocation[i].P2 == 0 && Allocation[i].P3 == 0){finish[i] = true;ArrLock.Remove(i);}else{finish[i] = false;}}while (possible){int n = 0;for (int i = 0; i < Allocation.Length; i++){if (finish[i] == false && Claim[i].P1 - Allocation[i].P1 <= Currentaviail.P1&& Claim[i].P2 - Allocation[i].P2 <= Currentaviail.P2 && Claim[i].P3 - Allocation[i].P3 <= Currentaviail.P3){Currentaviail.P1 += Allocation[i].P1;Currentaviail.P2 += Allocation[i].P2;Currentaviail.P3 += Allocation[i].P3;finish[i] = true;ArrLock.Remove(i);n++;}}if (n == 0){possible = false;}}if (ArrLock.Count != 0){string str = "";for (int j = 0; j < ArrLock.Count; j++){str += " " + ArrLock[j].ToString();}MessageBox.Show("产生死锁的进程为"+str+"确定解除? ");//messagetext.Text = "死锁!!!产生死锁的进程为" + str + "系统尝试解除中。
操作系统实验二报告一.实验名称:死锁的检测与解除二.实验目的:观察死锁产生的条件,并使用适当的算法,有效的防止和避免死锁的发生。
三.实验内容:死锁的检测算法:1.找出不再申请资源的进程,将它们所占的资源与系统中还剩余的资源加在一起作为“可分配的资源”,同时对这些进程置标志;2.检测所有无标志的进程,找出一个所需资源量不超过“可分配的资源”量的进程,将其所占用的资源添加到“可分配的资源”中,同时为该进程置标志;重复2)直到所有进程均有标志或无标志的进程的所需资源量均超过“可分配的资源”量;3.若进程均有标志,说明系统当前不存在死锁;若存在无标志的进程,则表示系统当前已有死锁形成,这些无标志的进程就是一组处于死锁状态的进程。
死锁的解除:当死锁检测程序检测到有死锁存在时,一般采用两种方式来解除死锁:1.终止进程:终止一个或多个涉及死锁的进程的执行,收回它们所占的资源再分配。
2.抢夺资源:从涉及死锁的一个或几个进程中抢夺资源,把夺来的资源再分配给卷入死锁的其他进程,直到死锁解除。
四.实验代码:#include <iostream>using namespace std;其中系统可用资源数为 2 1 0 0给进程3 分配资源数0 1 0 0六.实验心得:加深理解了有关资源申请分配、检测以及避免死锁等概念,了解死锁和避免死锁的具体实施方法。
死锁的解除实质上就是如何让释放资源的进程能够继续运行.为了解除死锁就要剥夺资源,此时,需要考虑一下几个问题:选择一个牺牲进程,即要剥夺哪个进程的哪些资源剥夺的进程如何再次运行.怎样保证不发生”饿死”现象“最小代价”,即最经济合算的算法,使得进程回退带来的开销最小.但是,”最小开销”是很不精确的,进程重新运行的开销包括很多因素:进程的优先级、该进程使用的资源种类和数量为完成任务,进程还需要多少资源有多少进程要被撤销、该进程被重新启动运行的次数.。
只有综合考虑各个进程之间的关系,跟资源的关系,才能搞好的解除死锁。
Deadlock Avoidance•Maximum resource requirement must be stated in advance(预先必须申明每个进程需要的资源总量)•Processes under consideration must be independent; no synchronization requirements (进程之间相互独立,其执行顺序取决于系统安全,而非进程间的同步要求)•There must be a fixed number of resources to allocate(系统必须提供固定数量的资源供分配)•No process may exit while holding resources(若进程占有资源,则不能让其退出系统)Deadlock Detection(检测死锁)•检测死锁不同于预防死锁,不限制资源访问方式和资源申请。
•OS周期性地执行死锁检测例程,检测系统中是否出现“环路等待”。
Strategies once Deadlock Detected •Abort all deadlocked processes.•Back up each deadlocked process to some previously defined checkpoint, and restart all process.–original deadlock may occur.•Successively abort deadlocked processes until deadlock no longer exists.•Successively preempt resources until deadlock no longer exists.Selection Criteria Deadlocked Processes•Least amount of processor time consumed so far. •Least number of lines of output produced so far. •Most estimated time remaining.•Least total resources allocated so far. •Lowest priority.。
操作系统(实验报告)死锁的检测与解除姓名:*****学号:****专业班级:***学验日期:2011/12/2指导老师:***一、实验名称:死锁的检测和解除二、实验内容:编程实现对操作系统死锁的检测和解除,利用数据的动态输入,解锁时采用的是释放占用系统资源最大的进程的方法来实现。
三、实验目的:熟悉死锁检测与的解除的算法,深入理解死锁的检测与解锁的具体方法,加深对死锁问题深刻记意。
并且进一步掌握死锁的条件,死锁定理等相关知识。
四、实验过程1.基本思想:利用资源分配图来理解此问题,可以认为此图就是由一组结点N和一组边E 所组成的一个对偶G=(N1E);把N分为互斥的两个子集进程P结点和资源R 结点,进程结点集和资源结点集,凡是属于E中的一个边,都连接着P中的一个结点和R中的一个结点由P中的一个结点指向R中的一个结点是资源请求边,而由R中的一个结点指向P中的一个结点的边称为资源分配边,在这个图中找到一个既不阻塞又不独立的结点Pi,如果是在顺利的情况下,则该进程可以获得足够资源而继续运行,运行完释放所有资源,这就可以说是消除了它的请求边和分配边,让它成为一个孤立的点,再继续,分配给请求资源的进程……这样循环下去直到所有的进程都能成为孤立的点,或是出现了无法消除的环状,若是出现了环状,即出现了死锁,采取释放占用资源最多的进程的方法来解决问题,直到最后所有的进程结点P均成为孤立的点。
解锁才算成功,程序才能结束。
2.主要数据结构:(1)可利用资源向量Available.这是一个含有m类资源的数组,用来表示每种资源可用的的数量。
(2)把不占用任何资源,且没有申请资源的进程,列入数组finish中,并赋值true。
(3)从进程集合中找到一个Request<=Work的进程,做如下的处理:将其资源分配图简化,释放出资源,增加Work的量,做Work=Work+Allocation 并将它的标志位finish也设为true.(4)如果不能把所有的进程标志位都赋值为true,则出现了死锁,开始采取解锁的方案。
死锁的简单例子c语言死锁是指两个或多个进程在执行过程中因争夺资源而造成的一种互相等待的现象,导致各个进程都无法继续执行的情况。
在C语言中,我们可以通过多线程来模拟死锁的简单例子。
下面是一个简单的C语言多线程死锁示例:c.#include <stdio.h>。
#include <pthread.h>。
pthread_mutex_t mutex1 = PTHREAD_MUTEX_INITIALIZER;pthread_mutex_t mutex2 = PTHREAD_MUTEX_INITIALIZER;void thread1_function(void arg) {。
pthread_mutex_lock(&mutex1);printf("Thread 1: Holding mutex 1...\n");sleep(2);printf("Thread 1: Waiting for mutex 2...\n");pthread_mutex_lock(&mutex2);printf("Thread 1: Holding mutex 2 and mutex 1...\n");pthread_mutex_unlock(&mutex2);pthread_mutex_unlock(&mutex1);return NULL;}。
void thread2_function(void arg) {。
pthread_mutex_lock(&mutex2);printf("Thread 2: Holding mutex 2...\n");sleep(2);printf("Thread 2: Waiting for mutex 1...\n");pthread_mutex_lock(&mutex1);printf("Thread 2: Holding mutex 1 and mutex 2...\n");pthread_mutex_unlock(&mutex1);pthread_mutex_unlock(&mutex2);return NULL;}。
死锁的检测与解除--操作系统实验报告题目:死锁的检测与解除指导老师:班级:姓名:学号:时间:实验二 死锁的检测与解除一、实验目的系统为进程分配资源时并不一定能满足进程的需求,因此检测系统的安全性是非常有必要的。
安全性的检测在之前的实验中用银行家算法得以实现,此次实验增加了另一个问题:即当系统死锁时如何解除死锁。
通过此次实验,可以深刻的体会死锁的检测与解除的方法。
二、实验内容编程实现死锁的检测与解除,并上机验证。
实验环境:Microsoft Visual Studio 2010三、算法描述程序中的数据结构:1) 可用资源向量Available : 这是一个含有m 个元素的数组,其中的每一个元素代表一类可利用资源数目。
2) 最大需求矩阵Max : 它是一个n m ⨯的矩阵,定义了系统中n 个进程中得每一个进程对m 类资源的最大需求。
3) 可分配矩阵Allocation : 这也一个n m ⨯的矩阵,定义了系统中每一类资源当前已分配给每一进程的资源数。
4) 需求矩阵Need : 这表示每一个进程尚需的各类资源数。
5) 综上所述:[][][][][][]Need i j Max i j Allocation i j =-。
该程序是在银行家算法的基础上添加了死锁的解除模块得来的,死锁的解除采用的方法是:找到已分配资源最大的死锁进程,剥夺其已分配资源,再次检测是否发生死锁。
1) 设i request 是进程i P 的请求向量,如果[]i request j K =,表示进程i P 需要K 个j R 类型起源。
当i P 发出资源请求后,进行检查,如果合格,修改Available 、Allocation 、Need 的值。
2) 用安全性算法检查是否存在安全序列,如果存在,输出安全序列;如果不存在,即为死锁,进行解锁操作。
3) 统计[,]Allocation i j 的值,找出占用资源最多的进程i P ,将其撤销,回收占用的资源,修改一下的数据结构中的值:[]:[]+[,]Available j Available j Allocation i j =;[,]:0Allocation i j =;用安全性算法进行检查,如果仍有死锁,重复步骤3,知道解锁为止。
一、实验名称:死锁的检测与解除二、实验内容:设计一个 n个并发进程共享m个系统资源的系统。
进程可动态申请资源和释放资源,系统按各进程的申请动态的分配资源。
要求用死锁检测算法检测当某一进程提出资源分配请求时,系统会不会陷入死锁状态;如若陷入死锁状态要求用某种算法解除死锁三、实验目的:当系统为进程分配资源时,若未采取任何限制性措施,则系统必须提供检测和解除死锁的手段,为此,系统必须做到:(1)保存有关资源的请求和分配信息;(2)提供一种算法,以利用这些信息来检测系统是否已进入死锁状态。
某一状态为死锁状态的充分条件是:当且仅当某一状态的资源分配图是不可完全简化的。
通过该实验,可以充分理解死锁的检测与解除的基本原理。
四、实验过程:a)基本思想先对各进程提出的请求资源数进行检查,即检查请求的资源数是否大于可用资源数。
若满足请求,则各进程完成执行。
若陷入死锁状态,则利用撤销进程的方法来解除死锁。
在本实验中,撤销占资源数最多的死锁进程。
b)主要数据结构(1)可利用资源向量Available,它表示了m类资源中每一类资源的可用数目。
(2)把不占用资源的进程(向量Allocation i:=0)记入P[L]序列中。
(3)从进程集合中找到一个Request i<=Work的进程,作如下处理:①将其资源分配图简化,释放出资源,增加工作向量Work:=Work+Allocation i。
②将它记入P[L]中。
(4)若不能把所有的进程都记入P[L]中,便表明系统状态S的资源分配图示不可完全简化的。
因此,该系统状态将发生死锁。
(5)将发生死锁的进程占有的各资源总数记入sum[i]中,得到使sum最大的i值,撤销进程i,若仍发生死锁,则继续撤销下一个进程,直到死锁解除。
若撤销至仅剩一个进程时,还未能解除死锁,则该死锁状态不能解除。
c)流程图★check()函数★jiesuo()函数截屏不产生死锁的情况发生死锁,无法解除的情况发生死锁,并成功解除的情况源程序:#include <iostream>#include <stdio.h>#include <stdlib.h>#include <string.h>using namespace std;//定义全局变量const int x=50,y=50; //x为进程个数y为资源种类数int Available[y]; //各资源可利用的数量int Allocation[x][y]; //各进程当前已分配的资源数量int Request[x][y]; //申请多少资源int Work[y]; //工作向量,表示系统可提供给进程继续运行所需的各类资源数量int Finish[x]; //表示系统是否有足够的资源分配给进程,1为是int p[x]; //存储安全序列int sum[x];//存储各进程占有的总资源数int i,j; //i表示进程,j表示资源int n,m; //n为进程i的数量,m为资源j种类数int l=0; //l用来记录有几个进程是Finish[i]=1的,当l=n是说明系统状态是安全的int c=0; //记数器,记录可执行的进程数//函数声明void chushihua(); //初始化函数bool check(); //检查是否产生死锁算法void show(); //函数show,输出当前状态void jiesuo(); //解除死锁算法void jieshu(); //结束函数void judge();void chushihua(){cout<<"输入进程的数量: ";//从此开始输入有关数据cin>>n;cout<<"输入资源种类数: ";cin>>m;cout<<endl<<"输入各种资源当前可用的数量( "<<m<<" 种): "<<endl;for (j=0; j<m; j++)//m为资源数{cout<<"输入资源"<<j<<" 可利用的数量Available["<<j<<"]: ";cin>>Available[j]; //输入数字的过程Work[j]=Available[j]; //初始化Work[j],它的初始值就是当前可用的资源数}cout<<endl<<"输入各进程当前已分配的资源数量Allocation["<<n<<"]["<<m<<"]: "<<endl;for (i=0; i<n; i++) //n为进程数{for (j=0; j<m; j++)//m为资源数{cout<<" 输入进程"<<i<<" 当前已分配的资源"<<j<<" 数量: ";cin>>Allocation[i][j];}cout<<endl;Finish[i]=0;//初始化Finish[i]}cout<<endl<<"输入各进程对各类资源的请求Request["<<n<<"]["<<m<<"]: "<<endl;for (i=0; i<n; i++)//n为进程数{for (j=0; j<m; j++)//m为资源数{cout<<" 输入进程"<<i<<" 对资源"<<j<<" 的请求数: ";cin>>Request[i][j];}cout<<endl;}cout<<endl<<"初始化完成"<<endl;}//显示当前状态函数void show() //函数show,输出当前资源分配情况{int i,j; //局部变量,i表示进程,j表示资源int All[y]; //各种资源的总数量int L1; //局部变量L1cout<<"当前的状态为:"<<endl;cout<<"各种资源的总数量:"<<endl;for (j=0;j<m;j++)//m为资源数{cout<<" 资源"<<j<<": ";All[j]=Available[j]; //总数量=可用的+已分配的for(i=0;i<n;i++) //n为进程数All[j]+=Allocation[i][j];cout<<All[j]<<" ";}cout<<endl<<"当前各种资源可用的量为(available):"<<endl;for(j=0;j<m;j++)//m为资源数cout<<" 资源"<<j<<": "<<Available[j]<<" ";cout<<endl<<"各进程已经得到的资源量(allocation): "<<endl;for(i=0;i<m;i++)//m为资源数{cout<<" 资源"<<i<<" ";}cout<<endl;for(L1=0;L1<n;L1++)//n为进程数{cout<<"进程"<<L1<<": ";for (j=0;j<m;j++)cout<<Allocation[L1][j]<<" ";cout<<endl;}cout<<endl<<"各进程对各类资源的请求量(Request):"<<endl;for(i=0;i<m;i++)//m为资源数{cout<<" 资源"<<i<<" ";}cout<<endl;for(L1=0;L1<n;L1++){cout<<"进程"<<L1<<": ";for (j=0;j<m;j++)cout<<Request[L1][j]<<" ";cout<<endl;}}//结束函数void jieshu(){cout<<endl<<endl;cout<<"\t\t 演示计算完毕"<<endl;cout<<endl<<endl;}//死锁检测bool check() //若无死锁则返回true{for(i=0;i<n;i++) //对任一进程进行判断n为进程数{int flag3=0;if(Finish[i]==0) //该进程还未执行完{for(j=0;j<m;j++) //m为资源数{if(Request[i][j]<=Work[j])//请求的资源数<可用资源数flag3=1;else{flag3=0;break;}}if(flag3==1){for(j=0;j<m;j++){Work[j]+=Allocation[i][j];Allocation[i][j]=0;}Finish[i]=1;p[l]=i;l++;i=-1;}}}if(l==n) //若所有的进程都放完,则返回ture,否则返回false{return true;//不存在死锁}else{return false;//存在死锁}}void jiesuo(){int temp,flag1=0;int b=n;//b用于控制已撤销的进程数for(i=0;i<n;i++) //统计死锁资源、释放{int total=0;if(Finish[i]==0) //i进程还未释放完资源{for(j=0;j<m;j++)//m为资源数{total=total+Allocation[i][j];//i进程总共占的资源数sum[i]=total;}}}temp=sum[0];//temp为最大资源数for(i=1;i<n;i++) //找出占资源数最多的死锁进程i{if(temp<sum[i]){temp=sum[i];flag1=i;}}cout<<"撤消占资源最多的进程:"<<flag1<<endl;for(j=0;j<m;j++) //回收资源{Work[j]+=Allocation[flag1][j];Allocation[flag1][j]=0;}Finish[flag1]=1; //完成flag1进程的操作l++;b--;if(check()){cout<<endl;cout<<"成功解除死锁"<<endl;}else{while(b>1){jiesuo(); //如果还没解除,继续放资源}if(b==1)cout<<"无法解除死锁!";}}void judge(){if(check())cout<<"不会发生死锁!"<<endl;else{cout<<"会发生死锁!死锁进程如下:"<<endl;for( i=0;i<n;i++) //找出死锁进程{if(Finish[i]==0)cout<<i<<" ";}cout<<endl;jiesuo(); //解锁}}void main() //主函数{cout<<endl;cout<<" *******************死锁的检测与解除示例******************* "<<endl;cout<<endl;cout<<endl;chushihua(); //初始化函数show(); //函数show,输出当前状态judge();check();jieshu();}五、实验小结死锁的检测与解除和银行家算法的数据结构基本相同,至于实验中所实施的死锁解除算法也只是简单撤销某一引起死锁进程所占有资源的简单释放,该实验只是简单模拟了死锁的检测与解除;最大的收获是对死锁定理的理解和对死锁解除算法的认识与实现机理实记。
C语⾔多线程编程死锁解析1.假设有两个线程 A线程负责输出奇数。
B线程负责输出偶数。
2.当A线程进⼊锁定状态是,主线程突然异常将A线程停⽌,这时将导致B线程也⽆法继续执⾏,处于死锁状态。
如下代码:#include <stdio.h>#include <stdlib.h>#include <pthread.h>pthread_mutex_t m;void *runodd(void *d){int i=0;for(i=1;;i+=2){pthread_mutex_lock(&m);printf("奇数:%d\n",i);usleep(100);pthread_mutex_unlock(&m);}}void *runeven(void *d){int i=0;for(i=0;;i+=2){pthread_mutex_lock(&m);printf("偶数:%d\n",i);usleep(100);pthread_mutex_unlock(&m);}}main(){pthread_t todd,teven;pthread_mutex_init(&m,0);pthread_create(&todd,0,runodd,0);pthread_create(&teven,0,runeven,0);sleep(5);printf("外部强制停⽌todd线程\n");pthread_cancel(todd);pthread_join(todd,(void**)0);pthread_join(teven,(void**)0);pthread_mutex_destroy(&m);}解决⽅法:运⽤2个函数(其实是2个宏)pthread_cleanup_pushpthread_cleanup_pop 这个对函数作⽤类似于atexit函数注意:这不是函数⽽是宏。
如何进行编程中的死锁检测和解决编程中的死锁检测和解决编程中的死锁问题是指两个或多个进程被永久地阻塞,它们都在等待彼此释放资源,从而无法继续执行的情况。
这是一种非常常见的并发编程问题,如果不及时解决,会严重影响系统的性能和可用性。
本文将介绍如何进行编程中的死锁检测和解决,以帮助开发人员有效地应对这一问题。
一、死锁检测死锁检测是指通过系统资源分配状态的周期性检测,来判断是否存在死锁的发生。
一般来说,常用的死锁检测算法有图论算法、资源分配图算法和银行家算法。
图论算法是通过构建进程和资源之间的有向图,来判断是否存在环路从而判断是否有死锁发生。
资源分配图算法是通过绘制资源和进程之间的关系图,来判断是否存在进程等待环路。
而银行家算法则是一种比较常用的死锁检测算法,它通过模拟系统资源的状态和进程请求资源的情况,来判断是否有死锁的可能性。
二、死锁解决在检测到死锁后,我们需要采取相应的解决方法来消除死锁。
常用的死锁解决方法有以下几种。
1. 资源剥夺法资源剥夺法是指当系统检测到死锁发生时,通过剥夺一些占用资源的进程来解除死锁。
这种方法需要根据一定的策略选择被剥夺的进程,并释放其占用的资源。
常用的策略包括优先级、资源占用量等。
2. 撤销进程法撤销进程法是指当检测到死锁发生时,直接撤销死锁的进程来解除死锁。
这种方法需要先选定一个进程进行撤销,然后释放该进程占用的资源。
选择哪个进程撤销可以根据一定的策略进行选择,如撤销时间、运行时间等。
3. 进程回退法进程回退法是指当检测到死锁发生时,要求造成死锁的进程回退到一个安全点(即无死锁状态),以解除死锁。
这种方法需要保存进程在发生死锁前的状态,通过回退操作将进程恢复到死锁发生之前的状态。
4. 进程终止法进程终止法是指当检测到死锁发生时,直接终止所有死锁进程来解除死锁。
这种方法比较激进,会丢失一定的进程信息和数据,因此需要慎重使用。
三、预防死锁在编程过程中,除了死锁的检测和解决,我们还应该注意预防死锁的发生。
实验二死锁的检测与避免—银行家算法一、实验目的1、了解进程产生死锁原因,了解为什么要避免死锁。
2、掌握银行家算法的数据结构,了解算法的执行过程,加深对银行家算法的理解。
二、实验内容及步骤采用银行家算法来实现一个n 个并发进程共享m 个系统资源的系统。
进程可以申请和释放资源,系统可以按照各进程的申请计算是否可以分配给其资源。
1、创建C语言工程项目,按照教材上的有关说明,定义相应的数据结构。
2、给各个数据结构设定合适的初始值。
注意:步骤1、2可同时进行,即利用C语言中的定义变量就可同时初始化的方式进行数值初设。
3、依据银行家算法的描述依次进行资源的试探性分配,直至成功或失败,成功则说明当前状态是安全的;失败后,还应该将资源回到初始状态,并进行另一次试探;只有所有的试探都失败了,才能说明当前状态是不安全的。
通常,这种试探性算法采用递归的方法是很合适的,程序也是很简洁的。
三、实验原理1、银行家算法的思路先对用户提出的请求进行合法性检查,即检查请求的是不大于需要的,是否不大于可利用的。
若请求合法,则进行试分配。
最后对试分配后的状态调用安全性检查算法进行安全性检查。
若安全,则分配,否则,不分配,恢复原来状态,拒绝申请。
2、银行家算法程序流程图(图2-1)银行家算法(图2-1)安全性算法(图2-2)四、实验结果及分析(一):1、T0时刻安全性2、P1发出请求向量Request 1(1,0,2)3、P4发出请求向量Request 4(3,3,0)4、P0发出请求向量Request 0(0,2,0) (二):1、 该状态是否安全?2、 P2发出请求向量Request (1,2,2,2)后,系统能否将资源分配给它?(三)、自行设计一组资源分配数据,要求资源数大于等于3,进程数大于等于3,有2次预分配。
实验二:死锁的检测和预防一、实验目的1、进一步了解进程的并发执行。
2、加强对进程死锁的理解3、是用银行家算法完成死锁检测二、实验内容给出进程需求矩阵C、资源向量R以及一个进程的申请序列。
使用进程启动拒绝和资源分配拒绝(银行家算法)模拟该进程组的执行情况。
要求:初始状态没有进程启动计算每次进程申请是否分配?如:计算出预分配后的状态情况(安全状态、不安全状态),如果是安全状态,输出安全序列。
每次进程申请被允许后,输出资源分配矩阵A和可用资源向量V。
每次申请情况应可单步查看,如:输入一个空格,继续下个申请三、实验环境VC++四、实验原理及实验思路1、安全状态:如果存在一个由系统中所有进程构成的安全序列P1,…,Pn,则系统处于安全状态。
安全状态一定是没有死锁发生。
2、不安全状态:不存在一个安全序列。
不安全状态一定导致死锁。
安全序列:一个进程序列{P1,…,Pn}是安全的,如果对于每一个进程Pi(1≤i≤n),它以后尚需要的资源量不超过系统当前剩余资源量与所有进程Pj (j < i )当前占有资源量之和。
3、银行家算法:我们可以把操作系统看作是银行家,操作系统管理的资源相当于银行家管理的资金,进程向操作系统请求分配资源相当于用户向银行家贷款。
操作系统按照银行家制定的规则为进程分配资源,当进程首次申请资源时,要测试该进程对资源的最大需求量,如果系统现存的资源可以满足它的最大需求量则按当前的申请量分配资源,否则就推迟分配。
当进程在执行中继续申请资源时,先测试该进程已占用的资源数与本次申请的资源数之和是否超过了该进程对资源的最大需求量。
若超过则拒绝分配资源,若没有超过则再测试系统现存的资源能否满足该进程尚需的最大资源量,若能满足则按当前的申请量分配资源,否则也要推迟分配。
4、银行家算法的思路:1),进程一开始向系统提出最大需求量.2),进程每次提出新的需求(分期贷款)都统计是否超出它事先提出的最大需求量.3),若正常,则判断该进程所需剩余剩余量(包括本次申请)是否超出系统所掌握的剩余资源量,若不超出,则分配,否则等待.5、银行家算法的数据结构:1),系统剩余资源量A[n],其中A[n]表示第I类资源剩余量.2),各进程最大需求量,B[m][n],其中B[j][i]表示进程j对i类资源最大需求.3),已分配资源量C[m][n],其中C[j][i]表示系统j程已得到的第i资源的数量.4),剩余需求量.D[m][n],其中D[j][i]对第i资源尚需的数目.五、流程图银行家算法:安全检测:六、源代码#include "string.h" #include <stdio.h> #include <stdlib.h>#define M 5#define N 3#define FALSE 0#define TRUE 1/*M个进程对N类资源最大资源需求量*/int MAX[M][N]={{7,5,3},{3,2,2},{9,0,2},{2,2,2},{4,3,3}};/*系统可用资源数*/int AVAILABLE[N]={10,5,7};/*M个进程对N类资源已经分配数量*/int ALLOCATION[M][N]={{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0}};/*M个进程还需要N类资源的资源量*/int NEED[M][N]={{7,5,3},{3,2,2},{9,0,2},{2,2,2},{4,3,3}};/*M个进程还需要N类资源的资源量*/int Request[N]={0,0,0};void main(){int i=0,j=0;char flag='Y';char finishFlag='Y';void showdata();void changdata(int);void rstordata(int);int chkerr(int);showdata();while(finishFlag=='Y'||finishFlag=='y') //可以分配资源{i=-1;while(i<0||i>=M) //判断申请的资源号是否有效{printf("请输入需申请资源的进程号(从0到%d,否则重输入!):",M-1);scanf("%d",&i);if(i<0||i>=M)printf("输入的进程号不存在,重新输入!\n");}printf("请输入进程%d申请的资源数\n",i);for (j=0;j<N;j++){printf("资源%d:",j);scanf("%d",&Request[j]);if(Request[j]>NEED[i][j]) //进程申请资源数大于进程还需要的资源{printf("进程%d申请的资源数大于进程%d还需要%d类资源的资源量!申请不合理,出错!请重新选择!\n",i,i,j);flag='N';break;}else{if(Request[j]>AVAILABLE[j]) //进程申请资源数大于系统可用该类资源量{printf("进程%d申请的资源数大于系统可用%d类资源的资源量!申请不合理,出错!请重新选择!\n",i,j);flag='N';break;}}}if(flag=='Y'||flag=='y'){int result;changdata(i);result=chkerr(i);if(result==1){rstordata(i);showdata();}elseshowdata();}//else//showdata();printf("\n");printf("是否继续银行家算法演示,按'Y'或'y'键继续,按'N'或'n'键退出演示: ");getchar();scanf("%c",&finishFlag);}}void showdata() //显示各类资源的分配情况{int i,j;printf("系统可用的资源数为:\n");printf(" ");for (j=0;j<N;j++){printf(" 资源%d:%d ",j,AVAILABLE[j]);}printf("\n");printf("各进程还需要的资源量:\n");for (i=0;i<M;i++){printf(" 进程%d ",i);for (j=0;j<N;j++){printf("资源%d:%d ",j,NEED[i][j]);}printf("\n");}printf("各进程已经得到的资源量: \n");for (i=0;i<M;i++){printf(" 进程%d ",i);for (j=0;j<N;j++)printf("资源%d:%d ",j,ALLOCATION[i][j]);printf("\n");}}void changdata(int k){int j;for (j=0;j<N;j++){AVAILABLE[j]=AVAILABLE[j]-Request[j];ALLOCATION[k][j]=ALLOCATION[k][j]+Request[j];NEED[k][j]=NEED[k][j]-Request[j];}}void rstordata(int k){int j;for (j=0;j<N;j++){AVAILABLE[j]=AVAILABLE[j]+Request[j];ALLOCATION[k][j]=ALLOCATION[k][j]-Request[j];NEED[k][j]=NEED[k][j]+Request[j];}}int chkerr(int s) //检查是否能够分配该资源{int WORK,FINISH[M],temp[M];int i,j,k=0;for(i=0;i<M;i++)FINISH[i]=FALSE;for(j=0;j<N;j++){WORK=AVAILABLE[j];i=s;while(i<M){if (FINISH[i]==FALSE&&NEED[i][j]<=WORK){WORK=WORK+ALLOCATION[i][j];FINISH[i]=TRUE;temp[k]=i;k++;i=0;}else{i++;}}for(i=0;i<M;i++)if(FINISH[i]==FALSE){printf("\n系统不安全!!! 本次资源申请不成功!!!\n\n");return 1;}}printf("\n经安全性检查,系统安全,本次分配成功。
C++实现死锁的监测#include"iostream"#include"fstream"#include"vector"#include"windows.h"using namespace std;vector<int> have[500]; //每个进程已经有的资源vector<int> want[500]; //各个进程想要的资源int pro_size; //进程数int res_size; //资源种类数int res[500]; //每类资源的个数int work[500]; //当前可用资源数vector<int> Deadlock;bool* visited;bool* Dead_res;void DeadlockChain(int beg){visited[beg] = true;cout << "Process:" << beg << endl;for (int i = 0; i < want[beg].size(); i++)for (int j = 0; j < Deadlock.size(); j++)for (int k = 0; k < have[Deadlock[j]].size(); k++)if (have[Deadlock[j]][k] == want[beg][i]){Dead_res[want[beg][i]] = true;if (!visited[j])DeadlockChain(j);}for (int t = 0; t < have[beg].size(); t++)for (int j = 0; j < Deadlock.size(); j++)for (int k = 0; k < want[Deadlock[j]].size(); k++) if (want[Deadlock[j]][k] == have[beg][t]){Dead_res[have[beg][t]] = true; if (!visited[j])DeadlockChain(j);}}void read_data(){ifstream in;in.open("D://a.txt");if (!in)cout << "FILE OPEN FAILED!" << endl;memset(res, 0, 500);memset(work, 0, 500);//**********************************************//Read resin >> res_size;if (res_size > 500){cout << "Number of res should be small than 500" << endl;exit(-1);}for (int i = 0; i < res_size; i++){int temp;in >> temp;if (temp < 0){cout << "Illegal No. of res!" << endl;cout << "Please check your input data!" << endl;exit(-1);}res[i] = work[i] = temp;}//************************************************//Read proin >> pro_size;if (pro_size > 500){cout << "Number of pro should be small than 500" << endl;exit(-1);}for (int k = 0; k < pro_size; k++){int num;in >> num;int have_size;in >> have_size;for (int i = 0; i < have_size; i++){int temp;in >> temp;if (temp >= res_size){cout << "illegal res No.!" << endl;cout << "Please check your input data!" << endl;exit(-1);}work[temp]--;if (work[temp] < 0){cout << "Impossible res dispatch situation!" << endl;cout << "Please check your input data!" << endl;exit(-1);}have[num].push_back(temp);}//-------------------------------------------------------- int want_size;in >> want_size;for (int j = 0; j < want_size; j++){int temp;in >> temp;if (temp >= res_size){cout << "illegal res No.!" << endl;cout << "Please check your input data!" << endl;exit(-1);}want[num].push_back(temp);}}}//**********************************************************void Draw(){HWND hWnd = FindWindow("ConsoleWindowClass", NULL);HDC hDc = GetDC(hWnd);HPEN hPen1 = CreatePen(PS_SOLID, 2, 0x000000FF);//生成红线HPEN hPen2 = CreatePen(PS_SOLID, 2, 0x0000FF00);//生成蓝线SelectObject(hDc, hPen1);int i;for (i = 0; i < res_size; i++){Ellipse(hDc, i * 100, 0, i * 100 + 50, 50);char s[5];s[0] = 'R';s[1] = i + 48;s[2] = '/0';TextOut(hDc, i * 100 + 20, 25, s, 2);for (int k = 0; k < res[i]; k++)Ellipse(hDc, i * 100 + k * 10 + 5, 10, i * 100 + k * 10 + 15, 20);}for (i = 0; i < pro_size; i++){Rectangle(hDc, i * 100, 100, i * 100 + 50, 150);char s[5];s[0] = 'P';s[1] = i + 48;s[2] = '/0';TextOut(hDc, i * 100 + 20, 125, s, 2);}for (i = 0; i < 10; i++)cout << endl;for (i = 0; i < pro_size; i++)for (int k = 0; k < res_size; k++){int cnt = 5;int j;for (j = 0; j < have[i].size(); j++){if (have[i][j] == k){SelectObject(hDc, hPen2);MoveToEx(hDc, i * 100 + cnt, 100, NULL);LineTo(hDc, k * 100 + cnt, 50);cnt += 10;}cnt = 5;for (j = 0; j < want[i].size(); j++){if (want[i][j] == k){SelectObject(hDc, hPen1);MoveToEx(hDc, i * 100 + 50 + cnt, 100, NULL);LineTo(hDc, k * 100 + cnt, 50);cnt -= 10;}}}}//**********************************************************void ers(int i){system("pause");HWND hWnd = FindWindow("ConsoleWindowClass", NULL);HDC hDc = GetDC(hWnd);HPEN hPen = CreatePen(PS_SOLID, 2, 0x00000000);SelectObject(hDc, hPen);for (int k = 0; k < res_size; k++){int cnt = 5;int j;for (j = 0; j < have[i].size(); j++){if (have[i][j] == k){MoveToEx(hDc, i * 100 + cnt, 100, NULL);LineTo(hDc, k * 100 + cnt, 50);cnt += 10;}}cnt = 5;for (j = 0; j < want[i].size(); j++){if (want[i][j] == k){MoveToEx(hDc, i * 100 + 50 + cnt, 100, NULL);LineTo(hDc, k * 100 + cnt, 50);cnt -= 10;}}}}//**********************************************************void predigest(){Draw();bool finish[500]; //记录进程是否完成for (int index = 0; index < pro_size; index++){if (want[index].size() != 0){finish[index] = false;else{finish[index] = true;ers(index);for (int i = 0; i < have[index].size(); i++)work[have[index][i]]++;} //此时就可以回收资源}bool flag;do{flag = false;for (int i = 0; i < pro_size; i++)if (!finish[i]){int temp[500];memset(temp, 0, 500);for (int k = 0; k < want[i].size(); k++){temp[want[i][k]]++;}bool ok = true;for (int j = 0; j < res_size; j++)if (temp[j] > work[j]){ok = false;break;}//可以分配?if (ok){ers(i);for (int t = 0; t < have[i].size(); t++){work[have[i][t]]++;} //回收资源have[i].clear();finish[i] = true;flag = true;}}} while (flag);for (int i = 0; i < pro_size; i++)if (finish[i] == false)Deadlock.push_back(i);if (Deadlock.size() != 0){cout << "DeadLock has happened!" << endl << endl;cout << "The processes & resources related to the deadlock is: " << endl;visited = new bool[Deadlock.size() + 5]; //use to id wheather the pro is visited DFSmemset(visited, 0, Deadlock.size() + 5);Dead_res = new bool[res_size + 5];for (int i = 0; i < Deadlock.size(); i++){if (!visited[i]){memset(Dead_res, 0, res_size + 5);DeadlockChain(i);cout << "Resource: ";for (int j = 0; j < res_size; j++)if (Dead_res[j])cout << j << " ";}cout << endl;}}elsecout << "All process had execued!" << endl; }int main(){read_data();predigest();return 0;}。
说道死锁问题的解决,⼀般情况下我们都是选择KILL进程,但如果不查出引起死锁的原因,死锁的现象则会频繁出现,其实只要通过查找引起死锁的的操作,就可以⽅便的解决死锁。
具体的解决⽅法如下: 1.再死锁发⽣时,我们可以通过下⾯的语法,查询到引起死锁的操作: use master go declare @spid int,@bl int DECLARE s_cur CURSOR FOR select 0 ,blocked from (select * from sysprocesses where blocked>0 ) a where not exists(select * from (select * from sysprocesses where blocked>0 ) b where a.blocked=spid) union select spid,blocked from sysprocesses where blocked>0 OPEN s_cur FETCH NEXT FROM s_cur INTO @spid,@bl WHILE @@FETCH_STATUS = 0 begin if @spid =0 select '引起数据库死锁的是: '+ CAST(@bl AS VARCHAR(10)) + '进程号,其执⾏的SQL语法如下' else select '进程号SPID:'+ CAST(@spid AS VARCHAR(10))+ '被' + '进程号SPID:'+ CAST(@bl AS VARCHAR(10)) +'阻塞,其当前进程执⾏的SQL语法如下' DBCC INPUTBUFFER (@bl ) FETCH NEXT FROM s_cur INTO @spid,@bl end CLOSE s_cur DEALLOCATE s_cur exec sp_who2 2.然后查找程序/数据库,此t_sql语法具体在什么地⽅使⽤。
实验名称:死锁的检测与解除*名:***
学号:**********
专业班级:创新实验班111 指导老师:**
实验题目
死锁的检测与解除
实验目的
为了更清楚系统对死锁是如何检测和当死锁发生时如何解除死锁
设计思想
首先需要建立和银行家算法类似的数组结构,先把孤立的进程(没有占用资源的进程)放入一个数组中,根据死锁原理,找出既不阻塞又非独立的进程结点,使之成为孤立的结点并放入孤立数组中,再释放该进程的占用资源,继续寻找下一个孤立结点,如果所有进程都能放入孤立数组中,则系统不会发生死锁,如果有进程不能放入,则系统将发生死锁,并进行死锁解除,撤消所有的死锁进程,释放它们占用的资源。
主要数据结构
和银行家算法类似,需要建立相应的数组
int allocation[M][M];
int request[M][M];
int available[M];
int line[M]; //管理不占用资源的进程
int no[M]; //记录造成死锁的进程
int work[M];
流程图
开始
结束
输入总进程
数
输入资源数
输入Request
矩阵
输入Allocation
矩阵
是否发生死锁
死锁解除
否
是
输入available
矩阵
运行结果
图(1)不会发生死锁时
图(1)当发生死锁时
附录
源代码如下:
# include "stdio.h"
# define M 50
int allocation[M][M];
int request[M][M];
int available[M];
int line[M];
int no[M];
int n,m,i,j,f,a=0;
main()
{
void check();
void remove();
void show();
printf("输入进程总数:");
scanf("%d", &n);
printf("输入资源种类数量:");
scanf("%d", &m);
printf("输入进程已占用的资源Allocation:\n");
for(i=0;i<n;i++)
for(j=0;j<m;j++)
scanf("%d", &allocation[i][j]);
printf("输入进程的请求矩阵request:\n");
for(i=0;i<n;i++)
for(j=0;j<m;j++)
scanf("%d",&request[i][j]);
printf("输入系统可利用资源available:\n");
for (j=0;j<m;j++)
scanf("%d", &available[j]);
show();
check();
f=1;
for(i=0;i<n;i++)
{
if(line[i]==0)
{f=0;
no[a++]=i;//记录死锁序号
}
}
if(f==0)
{
printf("该系统将发生死锁!\n");
printf("造成死锁的进程为:");
for(i=0;i<n;i++)
printf("%2d",no[i]);
printf("\n");
remove();
show();
}
else{
printf("不会发生死锁!\n");
}
}
void check()//死锁检测
{
int k,;
int x;
int work[M];
for(i=0;i<n;i++)
line[i]=0;
for(i=0;i<n;i++) //(2)
{ x=0;
for(j=0;j<m;j++)
{
if(allocation[i][j]==0)
x++;
if(x==m)
line[i]=1;
}
}
for(j=0;j<m;j++)//(3)
work[j]=available[j];
k=n;
do{
for (i=0;i<n; i++)
{
if(line[i]==0)
{
f=1; //空置条件是否满足
for (j=0;j<m; j++)
if (request[i][j]>work[j])
f=0;
if (f==1) //找到满足条件的进程
{ line[i]=1;
for (j=0;j<m; j++)
work[j]=work[j]+allocation[i][j]; //释放资源
available[j]=work[j];
}
}
}
k--;
}while(k>0);
}
void remove() //死锁解除
{
for(i=0;i<n;i++)
{
if(line[i]==0)
{
for(j=0;j<m;j++)
{
available[j]+=allocation[i][j];
allocation[i][j]=0;
request[i][j]=0;
}
}
}
printf("死锁解除!\n");
}
void show()
{
printf("进程");
printf(" ");
printf("allocation");
printf(" ");
printf("request");
printf(" ");
printf("available");
printf("\n");
for (i=0;i<n; i++)
{
printf("%2d",i);
printf(" ");
for(j=0;j<m; j++)
printf("%2d",allocation[i][j]);
printf(" ");
for(j=0;j<m; j++)
printf("%2d",request[i][j]);
printf(" ");
for(j=0;j<m; j++){
if(i>0)
break;
printf("%2d",available[j]);
}
printf("\n");
}
}。