`
zzg
  • 浏览: 124613 次
  • 性别: Icon_minigender_1
社区版块
存档分类
最新评论

数据库死锁问题及银行家算法

阅读更多

在操作系统的设计中,我们往往无法回避一个问题,那就是进程对有限资源的占用问题。在计算机系统中有很多独占性的资源,在任一时刻,它们都只能被一 个进程使用。常见的有打印机、磁带驱动器等。例如:两个进程同时打印会引起打印混乱。鉴于此,操作系统全都具有授权一进程(临时)独占地访问某一种资源的 能力。

在很多情形中,需要一个进程独占地访问若干种资源而不是一种。例如将一个大文件由磁带拷贝至打印机,进程需要同时访问磁带驱动器和打印机,并且不允 许其他进程这时访问它们。在只有一个进程的系统中,该进程可以要求任何它所需要的资源,然后进行工作。但是,在一个多道程序系统中,就有可能出现严重的问 题。例如,两个进程分别准备打印一个非常大的磁带文件。进程A申请打印机,并得到授权。进程B申请磁带机,也得到授权。现在,A申请磁带机,但该请求在B 释放磁带机前会被拒绝。不幸的是,B非但不放弃磁带机,而且去申请打印机,而A在申请到磁带机之前也不会释放打印机。这时,两个进程都被阻塞,并且保持下 去,这种状况就是死锁(deadlock).

下面系统阐述一下死锁的定义:所谓死锁,就是多个进程循环等待它方占有的资源而无限期的僵持下去的局面。显然,如果没有外力的作用,那么死锁涉及到的各个进程都将永远处于封锁状态。

计算机系统产生死锁的根本原因就是资源有限且操作不当。即:一种原因是系统提供的资源太少了,远不能满足并发进程对资源的需求。这种竞争资源引起的 死锁是我们要讨论的核心。例如:消息是一种临时性资源。某一时刻,进程A等待进程B发来的消息,进程B等待进程C发来的消息,而进程C又等待进程A发来的 消息。消息未到,A,B,C三个进程均无法向前推进,也会发生进程通信上的死锁。

我们可以对资源进行以下分类:
可重用资源(reusable resource):每个时刻只有一个进程使用,但不会耗尽,在宏观上各个进程轮流使用。如CPU、主存和辅存、I/O通道、外设、数据结构如文件、数据库和信号量。有可能剥夺资源:由高优进程剥夺低优进程,或OS核心剥夺进程。

P1
P2
... ...
Request(A) <a> Request(B) <a>
Request(B) <b> Request(A) <b>
Request(B) Request(A)
Request(A) Requsst(B)

可重用资源死锁
死锁发生:双方都拥有部分资源,同时在请求对方已占有的资源。如次序:P1<a> P2<a> P1<b> P2<b>

非可剥夺资源(consumable resource):可以动态生成和消耗,一般不限制数量。如硬件中断、信号、消息、缓冲区内的数据。

P1

P2

... ...
Receive(P2,M); <a> Receive(P1,Q); <a>
Send(P2,N); <b> Send(P1,R); <b>

非可剥夺资源死锁

死锁发生:双方都等待对方去生成资源,如次序:P1<a> P2<a>

总的来说,死锁和不可剥夺资源有关。我们讨论的重点放在不可剥夺资源。

使用一资源事件的顺序如下:申请资源,使用资源,释放资源。

另一种原因是由于进程推进顺序不合适引发的死锁。资源少也未必一定产生死锁。就如同两个人过独木桥,如果两个人都要先过,在独木桥上僵持不肯后退,必然会 因竞争资源产生死锁;但是,如果两个人上桥前先看一看有无对方的人在桥上,当无对方的人在桥上时自己才上桥,那么问题就解决了。所以,如果程序设计得不合 理,造成进程推进的顺序不当,也会出现死锁。

下面简述一下产生死锁的必要条件 :

如果在计算机系统中同时具备下面四个必要条件时,那么会发生死锁。换句话说,只要下面四个条件中有一个不具备,系统就不会出现死锁。

1.互斥条件:即某个资源在一段时间内只能由一个进程占有,不能同时被两个或两个以上的进程占有。

2.不可抢占条件:进程所获得的资源在未使用完毕之前,资源申请者不能强行地从资源占有者手中夺取资源,而只能由该资源的占有者进程自行释放。

3.占有且申请条件:进程至少已经占有一个资源,但又申请新的资源;由于该资源已被另外进程占有,此时该进程阻塞;但是,它在等待新资源之时,仍继续占用已占有的资源。

4.循环等待条件 :存在一个进程等待序列{P1,P2,…,Pn},其中P1等待P2所占有的某一资源,P2等待P3所占有的某一资源,……,而Pn等待P1所占有的某一资源,形成一个进程循环等待环。

死锁的有向图表示

面我们提到的这四个条件在死锁时会同时发生。也就是说,只要有一个必要条件不满足,则死锁就可以排除。

处理死锁的基本方法可归结为以下3种:

方法
资源分配策略
各种可能模式
主要优点
主要缺点
预防
Prevention
保守的;宁可资源闲置 一次请求所有资源<条件1>
资源剥夺
<条件3>
资源按序申请
<条件4>
适用于作突发式处理的进程;不必剥夺
适用于状态可以保存和恢复的资源
可以在编译时(而不必在运行时)就进行检查
效率低;进程初始化时间延长
剥夺次数过多;多次对资源重新起动
不便灵活申请新资源
避免
Avoidance
是“预防”和“检测”的折衷(在运行时判断是否可能死锁 寻找可能的安全的运行顺序 不必进行剥夺 必须知道将来的资源需求;进程可能会长时间阻塞
检测
Detection
宽松的;只要允许,就分配资源 定期检查死锁是否已经发生 不延长进程初始化时间;允许对死锁进行现场处理 通过剥夺解除死锁,造成损失

关于死锁的预防、检测与恢复,不是本文讨论的话题,感兴趣的读者可翻阅相关资料查找到这些信息。在这里,我们着重谈一谈死锁的避免。

我们说死锁预防是排除死锁的静态策略,它使产生死锁的四个必要条件不能同时具备,从而对进程申请资源的活动加以限制,以保证死锁不会发生;而死锁的避免是 排除死锁的动态策略,它不限制进程有关申请资源的命令,而是对进程所发出的每一个申请资源的命令加以动态地检查,并根据检查结果决定是否进行资源分配。就 是说,在资源分配过程中若预测有发生死锁的可能性,则加以避免。这种方法的关键是确定资源分配的安全性。 那么,是否存在一种算法,总能做出正确的选择从而避免死锁呢?答案是肯定的,但条件是必须事先获得一些特定的信息。

Dijkstra 于1965年提出了一个经典的避免死锁的算法----银行家算法(banker’s algorithm)。

其模型基于一个小城镇的银行家,他向一群客户分别承诺了一定金额的贷款,而他知道不可能所有客户同时都需要最大的贷款额。在这里,我们可将客户比作 进程,银行家比作操作系统。银行家算法就是对每一个客户的请求进行检查,检查如果满足它是否会引起不安全状态。假如是,那么不满足该请求;否,那么便满 足。

怎样得知一个状态是否安全呢?

所谓系统是安全的,是指系统中的所有进程能够按照某一种次序分配资源,并且依次地运行完毕,这种进程序列{P1,P2,…,Pn}就是安全序列。如果存在这样一个安全序列,则系统是安全的;如果系统不存在这样一个安全序列,则系统是不安全的。

更通俗一点地讲,检查状态是否安全的方法是看它是否有足够的剩余资源满足一个距最大需求最近的客户。如果有,那么这比投资被认为是能够收回的,然后接着检查下一个距最大需求最近的客户,如此反复下去。如果所有投资最终都被收回,那么该状态是安全的,最初的请求可以批准。
需要指出的是,不安全状态并不一定引起死锁,因为客户并不一定申请其最大贷款额度,但银行家不敢抱有这种侥幸心理。

在此,我们引入了两个向量:Resourse(资源总量)、Available(剩余资源量) 以及两个矩阵:Claim(每个进程的最大需求量)、Allocation(已为每个进程分配的数量)。它们共同构成了任一时刻系统对资源的分配状态。

向量模型:

R1

R2
R3

矩阵模型:

 
R1
R2
P1    
P2    
P3    

这里,我们设置另外一个矩阵:各个进程尚需资源量(Need),可以看出

Need = Claim – Allocation

因此,我们可以这样描述银行家算法:

设Request[i]是进程Pi的请求向量。如果Request[i , j]=k,表示Pi需k个Rj类资源。当Pi发出资源请求后,系统按下述步骤进行检查:

(1) if (Request[i]<=Need[i]) goto (2);
        else error(“over request”);
(2) if (Request[i]<=Available[i]) goto (3);
        else wait();

(3) 系统试探性把要求资源分给Pi(类似回溯算法)。并根据分配修改下面数据结构中的值。

Available[i] = Available[i] – Request[i] ;

Allocation[i] = Allocation[i] + Request[i];

Need[i] = Need[i]-Request[i];

(4) 系统执行安全性检查,检查此次资源分配后,系统是否处于安全状态。若安全,才正式将资源分配给进程以完成此次分配;若不安全,试探方案作废,恢复原资源分配表,让进程Pi等待。

系统所执行的安全性检查算法可描述如下:

设置两个向量:Free、Finish

工作向量Free是一个横向量,表示系统可提供给进程继续运行所需要的各类资源数目,它含有的元素个数等于资源数。执行安全算法开始时,

Free = Available.

标记向量Finish是一个纵向量,表示进程在此次检查中中是否被满足,使之运行完成,开始时对当前未满足的进程做Finish[i] = false;当有足够资源分配给进程(Need[i]<=Free)时,Finish[i]=true,Pi完成,并释放资源。

(1)从进程集中找一个能满足下述条件的进程Pi

① Finish[i] == false(未定)

② Need[i] <= Free (资源够分)

(2)当Pi获得资源后,认为它完成,回收资源:

Free = Free + Allocation[i] ;

Finish[i] = true ;

Go to step(1);

试探此番若可以达到Finish[0..n]:=true,则表示系统处于安全状态,然后再具体为申请资源的进程分配资源。否则系统处于不安全状态。

我们还举银行家的例子来说明:设有客户A、B、C、D,单一资源即为资金(R)。

下列状态为安全状态,一个安全序列为:C->D->B->A

A 1 6
B 1 5
C 2 4
D 4 7

Available = (2) ; Resourse = (10) ;

可以看出,银行家算法从避免死锁的角度上说是非常有效的,但是,从某种意义上说,它缺乏实用价值,因为很少有进程能够在运行前就知道其所需资源的最 大值,而且进程数也不是固定的,往往在不断地变化(如新用户登录或退出),况且原本可用的资源也可能突然间变成不可用(如磁带机可能坏掉)。因此,在实际 中,如果有,也只有极少的系统使用银行家算法来避免死锁。

分享到:
评论

相关推荐

    数据库死锁-解决死锁问题的三种办法

    1. **银行家算法**:这是一种经典的避免死锁的方法,通过预先计算系统的安全状态,只有在系统处于安全状态时才分配资源,避免了死锁的发生。 2. **资源预留**:在事务请求资源之前,系统会检查是否能够预留足够的...

    计算机操作系统银行家算法避免死锁

    在计算机操作系统中,银行家算法是一个经典的解决死锁问题的算法。下面我们将详细介绍银行家算法的原理、实现和应用。 一、银行家算法的原理 银行家算法的主要思想是通过对资源的分配和申请来避免死锁。该算法认为...

    银行家算法 死锁演示

    银行家算法是操作系统中一种经典的死锁预防策略,由艾兹格·迪杰斯特拉在1965年提出。这个算法主要用于确保系统的资源分配不会导致系统进入死锁状态,从而保证系统的安全性。死锁是指两个或多个并发进程在执行过程中...

    数据库死锁检测工具

    3. 死锁检测算法:应用如图着色算法、银行家算法等来检查是否存在循环等待,如果发现则表明存在死锁。 4. 解决策略:一旦检测到死锁,工具会采取相应措施,如回滚某个事务,让其释放资源,打破循环等待;或者设置...

    银行家算法实验报告及程序代码

    银行家算法是操作系统领域中一种著名的资源分配策略,主要用于避免系统的死锁问题。该算法由艾兹格·迪杰斯特拉在1965年提出,它的核心思想是预防性策略,通过预先分析系统资源的分配,确保系统不会进入不安全状态,...

    操作系统实验四银行家算法实验

    银行家算法广泛应用于操作系统、数据库管理系统、网络操作系统等领域,可以避免死锁的发生,提高系统的性能和可靠性。 知识点七:银行家算法的局限性 银行家算法的局限性是它只能避免死锁的发生,不能解决其他类型...

    银行家算法C#版-自动连access数据库

    《银行家算法C#版-自动连access数据库》 银行家算法是计算机操作系统领域中一种经典的资源分配策略,主要用于预防死锁的发生。该算法由E.F.科德于1965年提出,其核心思想是在系统运行过程中,对资源进行动态分配,...

    C#自编银行家算法

    C#实现银行家算法可以应用于各种需要避免死锁的系统中,例如操作系统、数据库系统、网络系统等。该算法可以确保系统的安全性和可靠性,避免系统中的死锁情况。 七、C#实现银行家算法的结论 C#实现银行家算法可以...

    c# 连接数据库 实现银行家算法

    "C#连接数据库实现银行家算法"是一个针对这些问题的实践项目,旨在利用C#编程语言来构建一个系统,该系统能够安全、有效地管理资源分配,以避免系统死锁,同时确保数据的稳定存储和检索。下面将详细讲解这个项目中的...

    操作系统c++银行家算法

    银行家算法是操作系统领域内用于解决死锁问题的一种重要方法。该算法通过模拟银行家如何分配资源给客户来确保系统的安全性,从而避免了死锁的发生。本文将详细介绍银行家算法的基本原理及其在C++中的实现细节。 ###...

    银行家算法(死锁避免)

    为了解决这一问题,一种名为“银行家算法”的死锁避免策略应运而生。本文将深入探讨银行家算法的原理、工作过程及其在实际应用中的价值。 银行家算法的核心思想源于银行的贷款审批机制。在银行中,贷款的审批基于一...

    银行家 算法 数据结构

    银行家算法是由Edsger Dijkstra提出的,主要用于解决多道程序系统中的死锁问题。在操作系统中,当多个进程竞争有限的资源时,可能会出现无法继续执行的情况,即死锁。银行家算法通过预分配和检查安全性,来预防这种...

    用C++编写的银行家算法

    2. 数据库系统:银行家算法可以用于解决数据库系统中的资源分配问题。 3. 分布式系统:银行家算法可以用于解决分布式系统中的资源分配问题。 银行家算法是一种有效的避免死锁的算法,可以广泛应用于各种计算机系统...

    银行家算法通用程序 学习

    银行家算法广泛应用于多道批处理系统、网络操作系统和数据库管理系统等领域,确保系统在处理多个并发请求时不会因资源竞争导致死锁。 六、通用程序实践 通过提供的“银行家算法通用程序.txt”,你可以深入理解并...

    银行家算法小程序+演示ppt

    5. **应用与扩展**:银行家算法不仅限于操作系统,也可以应用于其他资源有限且需要避免死锁的环境,如数据库管理系统、网络资源分配等。此外,还可以通过动态调整资源分配策略,如增加资源预分配的灵活性,来进一步...

    银行家算法报告

    银行家算法在多道程序设计系统中广泛应用,尤其在数据库、网络服务器等对资源管理和并发控制要求较高的场景。然而,它的主要限制在于需要预先知道所有进程的最大资源需求,这在实际操作中可能难以获取。此外,安全性...

    计算机操作系统-银行家算法

    其中,银行家算法是解决死锁预防问题的一种经典策略,它由E.F.科恩在1965年提出,用于模拟银行贷款系统,确保系统的安全性。本文将深入探讨银行家算法的工作原理及其在操作系统中的应用。 一、银行家算法概述 银行...

    银行家算法的实现与应用.docx

    银行家算法的基本思想是通过模拟银行借贷系统的分配策略,来避免操作系统中的死锁问题。该算法的数据结构主要包括三个部分:可用资源、进程当前状态和安全检查表。在这三个部分中,安全检查表是最重要的,它用于存储...

    银行家算法 vs2008 c#

    其中,银行家算法(Banker's Algorithm)作为一种预防死锁的策略,被广泛应用于解决并发环境中资源分配的安全性问题。本文将深入探讨银行家算法的基本原理,并结合C#编程语言,解析其实现过程。 银行家算法源于银行...

    银行家算法银行家算法.银行家算法.

    银行家算法广泛应用于操作系统中,特别是在分布式系统和网络环境中,用来防止因资源分配不当导致的死锁问题。此外,它也适用于数据库管理系统、云存储服务等需要高效管理和调度资源的场景。 总结,银行家算法是一种...

Global site tag (gtag.js) - Google Analytics