进程之死锁

一、死锁的定义

      多个进程,每个进程都无限等待被另一进程所占有的资源,因而永远无法得到的资源,这种现象称为进程死锁,这一组进程就称为死锁进程


二、死锁产生的原因     

(1)竞争资源:竞争不可剥夺资源(打印机,P1占用,P2要求打印机打印,则阻塞)

   资源为可剥夺资源和不可剥夺资源。

 可剥夺资源,指某进程在获得这类资源后,该资源可以再被其他进程或系统剥夺(如CPU和主存)

不可剥夺资源,系统把资源分配给某进程后不能强行收回,只能在进程用完后自行释放(打印机)

(2)进程推进顺序不当:2个进程都申请对方已占有的资源

                                    (P1占用R1请求R2,而P2占用R2请求R1),死锁                             


三、产生死锁的4个必要条件    

(1) 互斥条件:资源独占,一个资源每次只能给一个进程使用

(2) 不剥夺条件:不可抢占,资源申请者不能强行的从资源占有者手中夺取资源,资源只能由占有者自愿释放

(3) 请求和保持条件:部分分配,占有申请。在申请新的资源同时保持对原有资源的占有

(4) 环路等待条件:P1等待P2资源,P2等待P1占有的资源

四、死锁的解决策略 

(1)鸵鸟策略:不理睬

(2)预防策略:破坏死锁的4个必要条件

           破坏“互斥性”条件:允许一个资源可由多个进程同时使用(对有的资源行不通,如打印机)

           破坏“不可剥夺条件”:采用剥夺控制,在允许进程动态申请资源前提下,规定,申请新的资源不能立即满足,变为等待状态前,必须释放已占有的资源,若需要,重新再申请(适用于处理机和存储器)

           破坏“请求和保持”条件:采用资源静态分配法,要求每个进程在运行前必须一次性申请所需的所有资源,且仅当该进程所要资源均可满足时,才一次性分配。

           破坏“环路等待条件”:采用资源有序分配,把系统中所有资源编号,进程在申请资源时必须严格按资源编号的递增顺序执行,否则操作系统不予分配(缺点:资源编号增加顺序申请,与实际使用顺序不同,浪费资源)

(3)避免策略:精心地分配资源,动态地回避死锁

             基本思想,它不限制有关申请资源的命令,而是在系统运行过程中,对进程所发出每一个申请资源命令进行动态地检查,并根据检查结果决定是否进行资源分配。若分配可能引起系统死锁, 则不予分配,否则予以分配。就是说,在资源分配过程中若预测有发生死锁的可能性,则加以避免

            算法:银行家算法,分配资源之前,判断系统是否是安全的,若是,才分配。保证银行家状态从一个安全状态转向另一个安全状态——不死锁!(判断状态是否安全)。

  • 所谓安全状态,是指系统能按某种进程推进顺序( P1, P2, …, Pn),为每个进程Pi分配其所需资源,直至满足每个进程对资源的最大需求,使每个进程都可顺序地完成。此时称 P1, P2, …, Pn 为安全序列。如果系统无法找到一个安全序列,则称系统处于不安全状态。  

             银行家算法详情见https://blog.youkuaiyun.com/qq_36260974/article/details/84404369              

(4)检测和解除允许死锁发生,操作系统不断监视系统进展情况,判断死锁是否发生。一旦发生死锁,及时检测,并采取措施解除死锁

           死锁检测:资源分配图

           死锁解除:强制性地从系统中撤消进程并剥夺它们的资源给剩下的进程使用

           详情见https://blog.youkuaiyun.com/lierming__/article/details/79000632


### 线程死锁进程死锁的区别联系 #### 概念定义 线程死锁是指在同一进程中,两个或多个线程互相持有对方所需的资源并等待对方释放资源的情况[^1]。这种情况下,涉及的线程会陷入永久阻塞状态。 进程死锁则是指不同进程之间由于竞争有限资源而导致的一种僵局状态,其中每个进程都持有一些资源并等待其他进程持有的资源被释放[^4]。 两者的核心区别在于作用范围的不同:线程死锁发生在单个进程内部,而进程死锁则跨越不同的进程边界。 --- #### 死锁的原因分析 无论是线程还是进程死锁,其形成的根本原因是满足了四个必要条件——互斥条件、请求保持条件、不可剥夺条件和循环等待条件[^3]: - **互斥条件**:某些资源一次只能由一个实体(线程/进程)占用。 - **请求保持条件**:已占有部分资源的实体进一步申请新的资源,如果申请不到,则进入等待状态,但仍保留原有资源。 - **不可剥夺条件**:只有拥有者主动释放资源才能改变该资源的状态。 - **循环等待条件**:存在一组线程或者进程{P0, P1, ..., Pn},其中Pi正在等待P(i+1)%n所占有的资源。 具体到实现层面: - 对于线程死锁,常见原因是一个线程获取了一把锁之后再去尝试获取另一把锁,但由于后者已被其他线程锁定从而引发死锁。 - 而对于进程死锁,除了上述提到的竞争共享资源外,还可能因为通信机制设计不合理引起,比如两方都在等待对方发送消息。 --- #### 解决方案探讨 针对线程死锁进程死锁,有多种通用策略用于预防和解除这些问题: ##### 预防措施 1. **破坏请求保持条件** 可通过一次性分配所有所需资源来避免中间再次请求新资源的行为。例如,在数据库事务处理中采用这种方式减少潜在冲突点[^2]。 2. **破坏顺序依赖性** 给定一系列资源按照固定全局序号访问能够有效防止出现环路结构。即规定任何线程或进程必须先按编号从小到大依次取得各资源实例[^5]。 3. **超时重试机制** 设计合理的超时时间窗口,一旦发现长时间未能成功获得目标资源,则自动放弃当前操作重新排队尝试。 ##### 处理手段 当已经发生了死锁现象后,可采取如下补救办法之一: - **强制终止某个参者** 让其中一个受影响较大的线程或进程退出运行,并通知其余成员恢复正常工作流程。 - **调整优先级等级** 如果允许动态修改线程级别的话,可以让低级别的个体先行撤退以成全高级别的完成任务需求。 以下是基于Java语言的一个简单示例演示如何利用try-finally语句块确保及时解锁以防止单纯嵌套调用造成的隐患风险: ```java public class DeadlockAvoidanceExample { private final Object lockA = new Object(); private final Object lockB = new Object(); public void methodOne() { synchronized (lockA) { System.out.println("Thread 1: Holding lock A..."); try { Thread.sleep(10); } catch (InterruptedException e) {} synchronized (lockB) { System.out.println("Thread 1: Holding both locks!"); } } } public void methodTwo() { synchronized (lockB) { System.out.println("Thread 2: Holding lock B..."); try { Thread.sleep(10); } catch (InterruptedException e) {} synchronized (lockA) { System.out.println("Thread 2: Holding both locks!"); } } } } ``` 尽管此代码片段展示了两种方法分别加锁的过程,但如果严格按照预定次序执行就不会触发真正的死锁状况。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值