JAVA死锁及解决办法
- 格式:doc
- 大小:37.00 KB
- 文档页数:7
死锁的原因及解决方法死锁是指在并发系统中,两个或多个进程无限地等待对方释放已占用资源的状态。
死锁是多进程协作的一种异常情况,普遍存在于操作系统中。
理解死锁的原因以及采取适当的解决方法是确保计算机系统稳定运行的重要一环。
本文将探讨死锁的原因以及解决方法。
一、死锁的原因1. 互斥条件死锁发生的首要原因是资源的互斥使用。
即某一资源在同一时间只能被一个进程使用,如果有其他进程请求该资源,则必须等待,直至该资源被释放。
当出现多个进程同时占用多个资源,并且它们之间互相等待对方所占用的资源时,就可能产生死锁。
2. 请求与保持条件当一个进程请求资源而该资源又被其他进程占用时,请求进程必须等待,但同时保持已获得的资源不被释放。
如果多个进程都在等待其他进程占用的资源同时保持自己占用的资源,则可能形成循环等待,导致死锁的发生。
3. 不可剥夺条件资源分配后不能被剥夺的特性也会导致死锁。
即已分配的资源只能由拥有它的进程主动释放,其他进程无法将其剥夺。
当一个进程占用资源并等待获取其他资源时,如果其他进程无法剥夺已占用的资源,那么这种情况会导致死锁。
4. 循环等待条件当存在一组进程互相等待对方所占用的资源时,就会产生循环等待的条件。
这个循环等待的环路可以是单个资源的循环,也可以是多个资源之间的循环,但无论是哪种情况,只要出现循环等待,就会发生死锁。
二、死锁的解决方法1. 预防死锁预防死锁是通过破坏死锁发生的四个必要条件来防止死锁的产生。
其中最直接有效的方法是破坏循环等待条件,可以通过引入资源有序分配来达到目的。
也可以通过破坏请求与保持条件,即请求资源时一次性申请所需要的全部资源,而不是一次请求一个资源,以消除死锁发生的可能性。
2. 避免死锁避免死锁是在程序执行时进行资源分配,通过安全序列的原理来避免系统进入不安全状态。
所谓安全序列,即在系统中存在一个进程执行顺序,使得每个进程能够按照顺序执行并顺利完成。
通过安全序列的判断,可以避免死锁的发生。
hashmap死锁的解决方案对于Java开发者来说,HashMap是一种非常常见的数据结构。
不过,在多线程环境下使用HashMap时,容易出现死锁问题。
那么,应该如何解决这个问题呢?1. 死锁问题的简单介绍死锁是指在多任务执行时,两个或多个线程互相等待对方先释放资源而陷入的一种僵局。
在Java中,原因可能是多个线程同时访问同一资源(例如,使用同一个HashMap)。
如果每个线程都试图从HashMap中获取/添加/删除数据,那么就可能出现死锁问题。
2. 使用ConcurrentHashMap为了避免HashMap死锁问题,我们可以使用ConcurrentHashMap。
从名称上就可以看出,它是一个适用于并发环境的HashMap实现。
而且,在ConcurrentHashMap中,不同的线程可以同时对不同的段进行修改,也就是说,多个线程可以同时对一个ConcurrentHashMap进行操作,而不会出现死锁等并发问题。
3. 使用读写锁除了使用ConcurrentHashMap外,还可以使用读写锁来解决HashMap死锁问题。
读写锁分为读锁和写锁。
多个线程可以同时获得读锁,但只有一个线程可以获得写锁。
这样,在读多写少的场合,读操作就可以并发执行,从而提高了程序的效率。
4. 减小锁的粒度在多线程环境下使用HashMap时,还可以通过减小锁的粒度来解决死锁问题。
默认情况下,HashMap在进行put/get/remove等操作时会锁住整个map,从而导致并发问题。
我们可以通过将map分割为多个不同的段/区域,然后对每个段使用不同的锁来实现多线程并发。
这样,就可以大大减少锁的粒度,从而提高了并发性能。
5. 总结在多线程环境下使用HashMap时,为了避免死锁等并发问题,我们可以使用ConcurrentHashMap、读写锁、减小锁的粒度等方式来解决。
其中,ConcurrentHashMap和读写锁是最常见的解决方案。
java中遇到的问题和解决方案
目录
1. Java中遇到的问题
1.1 内存溢出问题
1.2 死锁问题
2. 解决方案
2.1 内存溢出问题的解决方案
2.2 死锁问题的解决方案
Java中遇到的问题
在Java编程过程中,经常会遇到各种各样的问题,其中两个比较常见的问题是内存溢出和死锁问题。
内存溢出问题是指程序在运行过程中申请的内存超过了系统能够分配给它的内存大小,导致程序崩溃。
这种问题通常发生在程序中频繁创建大量对象或者持续运行时间过长的情况下。
死锁问题则是指多个线程互相持有对方所需要的资源,导致彼此无法继续执行,进而导致程序无法正常运行。
死锁问题通常发生在多线程编程中,处理不当时很容易出现。
解决方案
针对内存溢出问题,可以通过一些方法来解决,比如增加堆内存大小、优化程序代码以减少内存占用、及时释放不再使用的对象等。
另外,可以使用一些工具来监控程序内存使用情况,及时发现并解决潜在的内存溢出问题。
对于死锁问题,可以通过合理地设计程序逻辑、避免使用过多的同步代码块、避免嵌套锁等方法来预防死锁的发生。
此外,可以使用一些工具来帮助检测程序中潜在的死锁问题,并及时处理。
综上所述,如果在Java编程过程中遇到内存溢出或死锁问题,可以通过上述方法来解决,确保程序的稳定运行。
数据库的死锁解决方法
数据库的死锁是指两个或多个事务在相互等待对方释放资源的情况下,无法继续执行的情况。
这种情况会导致数据库系统的性能下降,甚至会导致系统崩溃。
因此,解决数据库的死锁问题是非常重要的。
下面介绍几种解决数据库死锁的方法:
1. 优化数据库设计
数据库设计的不合理会导致死锁的发生。
因此,优化数据库设计是解决死锁问题的一个重要方法。
例如,可以通过合理的表结构设计、索引设计等方式来减少死锁的发生。
2. 优化事务处理
事务处理是数据库中最常见的操作,也是死锁发生的主要原因之一。
因此,优化事务处理是解决死锁问题的另一个重要方法。
例如,可以通过减少事务的并发性、缩短事务的执行时间等方式来减少死锁的发生。
3. 使用死锁检测和死锁超时机制
死锁检测和死锁超时机制是解决死锁问题的常用方法。
死锁检测是指系统在发现死锁时,通过回滚某些事务来解除死锁。
死锁超时机制是指系统在一定时间内检测到死锁后,强制回滚某些事务来解除死锁。
4. 使用锁粒度控制
锁粒度控制是指通过控制锁的范围来减少死锁的发生。
例如,可以通过使用行级锁、表级锁等方式来控制锁的范围,从而减少死锁的发生。
解决数据库的死锁问题是非常重要的。
通过优化数据库设计、优化事务处理、使用死锁检测和死锁超时机制、使用锁粒度控制等方式,可以有效地减少死锁的发生,提高数据库系统的性能和稳定性。
java + sqlite防止死锁方法(实用版3篇)《java + sqlite防止死锁方法》篇1在Java 中,防止死锁的方法主要有三种:1. 避免使用共享资源,即避免多个进程或线程同时访问同一共享资源。
可以使用synchronized 关键字或者显式锁来实现对共享资源的互斥访问,从而避免死锁的发生。
2. 强制实施资源分配顺序,即在分配资源时,按照一定的顺序进行分配,避免循环等待的情况。
可以使用wait 和notify 方法来实现线程之间的同步,从而避免死锁的发生。
3. 限制资源的分配,即在分配资源时,设置一定的限制,避免分配过多资源导致死锁的发生。
可以使用tryLock 方法来尝试获取锁,如果获取不到锁则等待一段时间后再尝试获取,从而避免死锁的发生。
在SQLite 中,防止死锁的方法主要是通过事务来实现的。
事务是一系列SQL 语句的集合,在执行过程中,要么全部执行成功,要么全部回滚失败。
通过使用事务,可以避免多个事务同时对同一数据进行修改,从而避免死锁的发生。
在Java 中使用SQLite 时,可以通过Java 的事务机制来实现死锁的防止。
具体来说,可以在Java 代码中使用事务来包裹SQLite 操作,从而保证操作的原子性、一致性和持久性。
《java + sqlite防止死锁方法》篇2在Java 中,防止死锁的方法主要有三种:1. 避免使用共享资源,即避免多个进程或线程同时访问同一共享资源。
在SQLite 中,可以通过使用事务来避免死锁,因为事务会确保所有操作都成功或都失败,从而避免了多个事务同时对同一资源进行访问的情况。
2. 强制实施资源分配顺序,即在分配资源时,按照一定的顺序进行分配,避免循环等待的情况。
在SQLite 中,可以使用锁来实现资源分配顺序,例如在插入数据时使用插入锁,保证插入操作的顺序。
3. 避免等待,即在进程或线程等待某个资源时,不要让其他进程或线程能够占用该资源。
在SQLite 中,可以通过使用锁来避免等待,例如在读取数据时使用读锁,保证读取操作的互斥性。
死锁和解决死锁的方法
死锁是指两个或多个进程因为相互等待对方所持有的资源而陷入无限等待状态,每个进程都在等待其他进程所持有的资源。
如果不采取措施解决死锁,系统将永远停滞下去。
解决死锁的方法有以下四种:
1. 预防死锁:通过合理规划资源的分配顺序,避免进程发生死锁。
例如,使用银行家算法预测系统的安全状态,判断在分配资源时是否会导致死锁的发生。
2. 避免死锁:基于资源需求量、可用资源量、已分配资源量等信息,动态地判断系统是否安全,是否存在死锁,从而避免死锁的发生。
例如,使用银行家算法,只有在系统安全状态才会分配资源,从而避免死锁的发生。
3. 检测死锁:为了避免死锁的发生,可以定期检测系统的资源分配状态,判断是否存在死锁。
一旦检测到死锁,可以通过回滚、剥夺资源等方法解除死锁。
例如,使用死锁检测算法来检测死锁并解除死锁。
4. 解除死锁:当检测到死锁时,可以采取解除死锁的措施,如剥夺某个进程所占用的资源、撤回某个进程的资源申请等,以解除死锁状态。
通常需要考虑到进程的优先级、资源占用量等因素,选择合适的解除死锁策略。
Java 死锁的解决方法及示例本文介绍了 Java 死锁的原因及几种常用的解决方法,并通过示例代码进行了说明。
Java 死锁的解决方法及示例死锁是指两个或多个进程(线程)因竞争资源而陷入的无法进行的状态。
在 Java 编程中,死锁通常是由于多个线程以不同的顺序请求共享资源所导致的。
为了解决死锁问题,Java 提供了多种方法,下面我们来一一介绍。
一、死锁的原因在 Java 中,死锁产生的主要原因是多个线程以不同的顺序请求共享资源。
例如,当线程 A 持有资源 1 并请求资源 2 时,线程 B 持有资源 2 并请求资源 1,此时两者都会等待对方释放资源,从而导致死锁。
二、解决死锁的方法1. 互斥锁互斥锁是 Java 中最基本的死锁解决方法。
通过给共享资源加锁,确保同一时刻只有一个线程可以访问资源。
当一个线程获取了锁后,其他线程只能在锁释放后才能访问资源。
这种方法可以有效避免死锁的发生。
2. 显式锁显式锁是 Java 中使用的一种锁,它比互斥锁更为灵活。
显式锁可以通过 try-finally 语句来确保锁的正确释放。
在 try-finally 语句块中,可以对共享资源进行操作,当操作完成时,无论是正常结束还是异常结束,都会自动释放锁。
这样可以避免因忘记释放锁而导致的死锁问题。
3. 信号量信号量是 Java 中用于处理多线程同步问题的一种机制。
通过设置一个计数器,表示某个共享资源的可用数量。
当一个线程获取到信号量时,计数器减 1;当线程释放信号量时,计数器加 1。
如果计数器为 0,则表示没有可用资源,线程需要等待其他线程释放资源。
这种方法可以有效避免死锁的发生。
4. 条件变量条件变量是 Java 中用于处理多线程同步问题的另一种机制。
通过设置一个布尔值,表示某个条件是否满足。
当一个线程判断条件不满足时,会释放所持有的资源并阻塞等待;当条件满足时,该线程会被唤醒并继续执行。
这种方法可以有效避免死锁的发生。
三、示例代码下面通过一个示例代码来说明 Java 死锁的解决方法。
java 解决死锁的方法以Java 解决死锁的方法死锁是多线程编程中常见的问题之一,它会导致程序无法继续执行,造成资源的浪费和系统的崩溃。
为了解决这个问题,我们可以使用一些方法来预防和处理死锁情况。
一、避免死锁的发生1. 破坏互斥条件:互斥条件是指资源只能被一个线程占用。
我们可以通过改进算法或者数据结构,减少对共享资源的竞争,从而避免死锁的发生。
2. 破坏占有和等待条件:占有和等待条件是指线程在等待其他线程释放资源的同时,自己占有的资源不释放。
为了避免死锁,我们可以要求线程在申请资源时一次性申请所有需要的资源,而不是逐个申请。
3. 破坏不可抢占条件:不可抢占条件是指线程在持有资源的情况下,其他线程无法抢占它的资源。
为了避免死锁,我们可以在必要的时候剥夺线程持有的资源,以满足其他线程的需求。
4. 破坏循环等待条件:循环等待条件是指多个线程形成一个循环等待资源的关系。
为了避免死锁,我们可以按照一定的顺序申请资源,使得线程之间不会形成循环等待的情况。
二、检测和解决死锁1. 使用jstack工具检测死锁:jstack是Java提供的一种线程堆栈跟踪工具,可以用来检测死锁。
通过查看线程堆栈信息,我们可以判断是否存在死锁的情况。
2. 使用synchronized的wait()和notify()方法解决死锁:在Java 中,我们可以使用synchronized关键字来实现线程的同步。
当线程需要等待某个条件时,可以调用wait()方法进入等待状态;当条件满足时,可以调用notify()方法唤醒等待的线程。
通过合理使用wait()和notify()方法,可以避免死锁的发生。
3. 使用Lock接口和Condition接口解决死锁:Java提供了Lock 接口和Condition接口,可以更灵活地控制线程的同步。
通过使用Lock接口和Condition接口,我们可以实现更精确的线程等待和唤醒,从而避免死锁的发生。
4. 使用线程池解决死锁:线程池是一种常用的线程管理机制,可以有效地控制线程的数量和复用。
程序中死锁检测的方法和工具翟宇鹏;程雪梅【摘要】死锁一直都是并发系统中最重要的问题之一,对死锁检测的研究一直都在不断地进行着.模型检测方法是一种重要的自动验证技术,越来越多地被用在验证软硬件设计是否规范的工作中.针对死锁检测的问题进行综述,统计已有的死锁检测方法的文献资料并给出统计结果.然后对搜集出来的文献进行分析,介绍许多动态以及静态的死锁检测方法.最后介绍两种常用的模型检测工具,提出使用模型检测工具进行死锁检测的思路与方法,并证实这种方法的可行性.【期刊名称】《现代计算机(专业版)》【年(卷),期】2017(000)003【总页数】5页(P41-44,53)【关键词】死锁检测;模型检测;文献计量分析【作者】翟宇鹏;程雪梅【作者单位】四川大学计算机学院,成都610065;四川大学计算机学院,成都610065【正文语种】中文随着计算机行业的不断发展,软件规模和复杂度也在不断扩大,软件故障已成为计算机系统出错和崩溃的主要因素。
死锁[1]是分布式系统以及集成式系统中的最重要的问题之一,也是影响软件安全的主要因素。
死锁会导致程序无法正常运行或终止,甚至导致系统崩溃,带来不必要的损失。
同时,死锁的运行状态空间过大,难于重现和修正等问题使其成为软件领域的难题之一,因此,如何有效地检测死锁,提高软件的可靠性和安全性,成为急需解决的问题。
本文针对10年内国内外各知名数据库中与死锁检测以及模型检测相关的论文进行查询、筛选、分类、比较、整理等,然后对整理好的论文进行总结,分析出死锁检测的方法并进行罗列比较,以及模型检测的工具以及方法,从而再将二者结合,找出模型检测工具在死锁检测里的应用。
对搜索出来的412篇论文的不同方向进行了计量分析,并对统计的数据进行了描述,以及通过计量分析来找出这方面研究领域的热点。
因为近10年的论文更能体现出研究的正确方向,所以对于论文时间进行分析,得知最近10年每年论文发表量随着时间在平缓地增多,可知对于这方面问题的研究总体保持在增长的状态。
进程死锁及解决办法一、要点提示(1)掌握死锁的概念和产生死锁的根本原因。
(2)理解产生死锁的必要条件--以下四个条件同时具备:互斥条件、不可抢占条件、占有且申请条件、循环等待条件。
(3)记住解决死锁的一般方法,掌握死锁的预防和死锁的避免二者的基本思想。
(4)掌握死锁的预防策略中资源有序分配策略。
(5)理解进程安全序列的概念,理解死锁与安全序列的关系。
(6)了解银行家算法。
(7)了解资源分配图。
(8)了解死锁的检测及恢复的思想。
二、内容简介在计算机系统中有很多一次只能由一个进程使用的资源,如打印机,磁带机,一个文件的I节点等。
在多道程序设计环境中,若干进程往往要共享这类资源,而且一个进程所需要的资源不止一个。
这样,就会出现若干进程竞争有限资源,又推进顺序不当,从而构成无限期循环等待的局面。
这种状态就是死锁。
系统发生死锁现象不仅浪费大量的系统资源,甚至导致整个系统崩溃,带来灾难性后果。
所以,对于死锁问题在理论上和技术上都必须给予高度重视。
死锁的概念死锁是进程死锁的简称,是由Dijkstra于1965年研究银行家算法时首先提出来的。
它是计算机操作系统乃至并发程序设计中最难处理的问题之一。
实际上,死锁问题不仅在计算机系统中存在,在我们日常生活中它也广泛存在。
什么是死锁我们先看看这样一个生活中的例子:在一条河上有一座桥,桥面较窄,只能容纳一辆汽车通过,无法让两辆汽车并行。
如果有两辆汽车A和B分别由桥的两端驶上该桥,则对于A车来说,它走过桥面左面的一段路(即占有了桥的一部分资源),要想过桥还须等待B车让出右边的桥面,此时A车不能前进;对于B车来说,它走过桥面右边的一段路(即占有了桥的一部分资源),要想过桥还须等待A车让出左边的桥面,此时B车也不能前进。
两边的车都不倒车,结果造成互相等待对方让出桥面,但是谁也不让路,就会无休止地等下去。
这种现象就是死锁。
如果把汽车比做进程,桥面作为资源,那麽上述问题就描述为:进程A 占有资源R1,等待进程B占有的资源Rr;进程B占有资源Rr,等待进程A占有的资源R1。
而且资源R1和Rr只允许一个进程占用,即:不允许两个进程同时占用。
结果,两个进程都不能继续执行,若不采取其它措施,这种循环等待状况会无限期持续下去,就发生了进程死锁。
在计算机系统中,涉及软件,硬件资源都可能发生死锁。
例如:系统中只有一台CD-ROM 驱动器和一台打印机,某一个进程占有了CD-ROM驱动器,又申请打印机;另一进程占有了打印机,还申请CD-ROM。
结果,两个进程都被阻塞,永远也不能自行解除。
所谓死锁,是指多个进程循环等待它方占有的资源而无限期地僵持下去的局面。
很显然,如果没有外力的作用,那麽死锁涉及到的各个进程都将永远处于封锁状态。
从上面的例子可以看出,计算机系统产生死锁的根本原因就是资源有限且操作不当。
即:一种原因是系统提供的资源太少了,远不能满足并发进程对资源的需求。
这种竞争资源引起的死锁是我们要讨论的核心。
例如:消息是一种临时性资源。
某一时刻,进程A等待进程B发来的消息,进程B等待进程C发来的消息,而进程C又等待进程A发来的消息。
消息未到,A,B,C 三个进程均无法向前推进,也会发生进程通信上的死锁。
另一种原因是由于进程推进顺序不合适引发的死锁。
资源少也未必一定产生死锁。
就如同两个人过独木桥,如果两个人都要先过,在独木桥上僵持不肯后退,必然会应竞争资源产生死锁;但是,如果两个人上桥前先看一看有无对方的人在桥上,当无对方的人在桥上时自己才上桥,那麽问题就解决了。
所以,如果程序设计得不合理,造成进程推进的顺序不当,也会出现死锁。
产生死锁的四个必要条件从以上分析可见,如果在计算机系统中同时具备下面四个必要条件时,那麽会发生死锁。
换句话说,只要下面四个条件有一个不具备,系统就不会出现死锁。
〈1〉互斥条件。
即某个资源在一段时间内只能由一个进程占有,不能同时被两个或两个以上的进程占有。
这种独占资源如CD-ROM驱动器,打印机等等,必须在占有该资源的进程主动释放它之后,其它进程才能占有该资源。
这是由资源本身的属性所决定的。
如独木桥就是一种独占资源,两方的人不能同时过桥。
〈2〉不可抢占条件。
进程所获得的资源在未使用完毕之前,资源申请者不能强行地从资源占有者手中夺取资源,而只能由该资源的占有者进程自行释放。
如过独木桥的人不能强迫对方后退,也不能非法地将对方推下桥,必须是桥上的人自己过桥后空出桥面(即主动释放占有资源),对方的人才能过桥。
〈3〉占有且申请条件。
进程至少已经占有一个资源,但又申请新的资源;由于该资源已被另外进程占有,此时该进程阻塞;但是,它在等待新资源之时,仍继续占用已占有的资源。
还以过独木桥为例,甲乙两人在桥上相遇。
甲走过一段桥面(即占有了一些资源),还需要走其余的桥面(申请新的资源),但那部分桥面被乙占有(乙走过一段桥面)。
甲过不去,前进不能,又不后退;乙也处于同样的状况。
〈4〉循环等待条件。
存在一个进程等待序列{P1,P2,...,Pn},其中P1等待P2所占有的某一资源,P2等待P3所占有的某一源,......,而Pn等待P1所占有的的某一资源,形成一个进程循环等待环。
就像前面的过独木桥问题,甲等待乙占有的桥面,而乙又等待甲占有的桥面,从而彼此循环等待。
注意:上面我们提到的这“四个条件”在死锁时会同时发生。
也就是说,只要有一个必要条件不满足,则死锁就可以排除。
死锁的预防前面介绍了死锁发生时的四个必要条件,只要破坏这四个必要条件中的任意一个条件,死锁就不会发生。
这就为我们解决死锁问题提供了可能。
一般地,解决死锁的方法分为死锁的预防,避免,检测与恢复三种(注意:死锁的检测与恢复是一个方法)。
我们将在下面分别加以介绍。
死锁的预防是保证系统不进入死锁状态的一种策略。
它的基本思想是要求进程申请资源时遵循某种协议,从而打破产生死锁的四个必要条件中的一个或几个,保证系统不会进入死锁状态。
〈1〉打破互斥条件。
即允许进程同时访问某些资源。
但是,有的资源是不允许被同时访问的,像打印机等等,这是由资源本身的属性所决定的。
所以,这种办法并无实用价值。
〈2〉打破不可抢占条件。
即允许进程强行从占有者那里夺取某些资源。
就是说,当一个进程已占有了某些资源,它又申请新的资源,但不能立即被满足时,它必须释放所占有的全部资源,以后再重新申请。
它所释放的资源可以分配给其它进程。
这就相当于该进程占有的资源被隐蔽地强占了。
这种预防死锁的方法实现起来困难,会降低系统性能。
〈3〉打破占有且申请条件。
可以实行资源预先分配策略。
即进程在运行前一次性地向系统申请它所需要的全部资源。
如果某个进程所需的全部资源得不到满足,则不分配任何资源,此进程暂不运行。
只有当系统能够满足当前进程的全部资源需求时,才一次性地将所申请的资源全部分配给该进程。
由于运行的进程已占有了它所需的全部资源,所以不会发生占有资源又申请资源的现象,因此不会发生死锁。
但是,这种策略也有如下缺点:1、在许多情况下,一个进程在执行之前不可能知道它所需要的全部资源。
这是由于进程在执行时是动态的,不可预测的;2、资源利用率低。
无论所分资源何时用到,一个进程只有在占有所需的全部资源后才能执行。
即使有些资源最后才被该进程用到一次,但该进程在生存期间却一直占有它们,造成长期占着不用的状况。
这显然是一种极大的资源浪费;3、降低了进程的并发性。
因为资源有限,又加上存在浪费,能分配到所需全部资源的进程个数就必然少了。
〈4〉打破循环等待条件,实行资源有序分配策略。
采用这种策略,即把资源事先分类编号,按号分配,使进程在申请,占用资源时不会形成环路。
所有进程对资源的请求必须严格按资源序号递增的顺序提出。
进程占用了小号资源,才能申请大号资源,就不会产生环路,从而预防了死锁。
这种策略与前面的策略相比,资源的利用率和系统吞吐量都有很大提高,但是也存在以下缺点:1、限制了进程对资源的请求,同时给系统中所有资源合理编号也是件困难事,并增加了系统开销;2、为了遵循按编号申请的次序,暂不使用的资源也需要提前申请,从而增加了进程对资源的占用时间。
死锁的避免上面我们讲到的死锁预防是排除死锁的静态策略,它使产生死锁的四个必要条件不能同时具备,从而对进程申请资源的活动加以限制,以保证死锁不会发生。
下面我们介绍排除死锁的动态策略--死锁的避免,它不限制进程有关申请资源的命令,而是对进程所发出的每一个申请资源命令加以动态地检查,并根据检查结果决定是否进行资源分配。
就是说,在资源分配过程中若预测有发生死锁的可能性,则加以避免。
这种方法的关键是确定资源分配的安全性。
1.安全序列我们首先引入安全序列的定义:所谓系统是安全的,是指系统中的所有进程能够按照某一种次序分配资源,并且依次地运行完毕,这种进程序列{P1,P2,...,Pn}就是安全序列。
如果存在这样一个安全序列,则系统是安全的;如果系统不存在这样一个安全序列,则系统是不安全的。
安全序列{P1,P2,...,Pn}是这样组成的:若对于每一个进程Pi,它需要的附加资源可以被系统中当前可用资源加上所有进程Pj当前占有资源之和所满足,则{P1,P2,...,Pn}为一个安全序列,这时系统处于安全状态,不会进入死锁状态。
虽然存在安全序列时一定不会有死锁发生,但是系统进入不安全状态(四个死锁的必要条件同时发生)也未必会产生死锁。
当然,产生死锁后,系统一定处于不安全状态。
2.银行家算法这是一个著名的避免死锁的算法,是由Dijstra首先提出来并加以解决的。
[背景知识]一个银行家如何将一定数目的资金安全地借给若干个客户,使这些客户既能借到钱完成要干的事,同时银行家又能收回全部资金而不至于破产,这就是银行家问题。
这个问题同操作系统中资源分配问题十分相似:银行家就像一个操作系统,客户就像运行的进程,银行家的资金就是系统的资源。
[问题的描述]一个银行家拥有一定数量的资金,有若干个客户要贷款。
每个客户须在一开始就声明他所需贷款的总额。
若该客户贷款总额不超过银行家的资金总数,银行家可以接收客户的要求。
客户贷款是以每次一个资金单位(如1万RMB 等)的方式进行的,客户在借满所需的全部单位款额之前可能会等待,但银行家须保证这种等待是有限的,可完成的。
例如:有三个客户C1,C2,C3,向银行家借款,该银行家的资金总额为10个资金单位,其中C1客户要借9各资金单位,C2客户要借3个资金单位,C3客户要借8个资金单位,总计20个资金单位。
某一时刻的状态如图所示。
(a) (b) (c) (d) C1 2(7) C2 2(1) C3 4(4)余额2银行家算法示意对于a 图的状态,按照安全序列的要求,我们选的第一个客户应满足该客户所需的贷款小于等于银行家当前所剩余的钱款,可以看出只有C2客户能被满足:C2客户需1个资金单位,小银行家手中的2个资金单位,于是银行家把1个资金单位借给C2客户,使之完成工作并归还所借的3个资金单位的钱,进入b 图。