【Linux】死锁(更新中)

文章目录

  • 一. 什么是死锁
  • 二. 死锁产生的四个条件
  • 三. 避免死锁
    • 1. 死锁检测算法
    • 2. 银行家算法
  • 结束语

【Linux】死锁(更新中)_第1张图片

一. 什么是死锁

  • 死锁是指一组进程中的各个进程均占有不会释放的资源,但因互相申请被其他进程所占用的不会释放的资源,而处于一种永久等待的状态。

就像下图(图片来自网络)

【Linux】死锁(更新中)_第2张图片

第一种死锁是,线程A和线程B同时让线程C让路,但因为空间狭窄,并且两人都互补想让,所以一直处于等待状态
第二种死锁是,线程A和线程B互相阻塞,都抢夺路权,并且不相让自己的,所以处于等待状态

二. 死锁产生的四个条件

死锁产生的四个条件属于必要条件,即如果出现死锁,必然由这四种条件导致,不过反之,可能还出现第5,第6种情况,也导致死锁。

  1. 互斥条件: 一个资源每次只能被一个执行流使用
  2. 请求与保持条件: 一个执行流因请求资源而阻塞时,对已获得的资源保持不释放
  3. 循环等待条件: 若干个执行流之间形成的一种头尾相接的循环等待资源的关系
  4. 不剥夺条件:一个执行流已获得的资源,在未使用完之前,不能被强行剥夺

三. 避免死锁

避免死锁的一种方法就是破坏上述的四个条件,只要破坏其中的任意一个,就不会产生死锁。

  • 对于互斥条件:我们可以尽量减少对临界资源的访问,减少加锁解锁的操作
  • 对于请求与保持条件:pthread_mutex_trylock函数,在多次加锁后,如果仍不成功,会解除自己所申请的锁。
  • 循环等待条件:使得加锁的顺序一致,比如两个线程都获取A,B两把锁。两个线程获取的顺序都是AB,减少交错的情况。如果一个线程AB,一个线程BA,那么一定会死锁。
  • 不剥夺条件:解锁操作允许其他线程进行,即可以剥夺资源。

还有一些其他方法:

  1. 避免锁未释放的场景
  2. 资源一次性分配

有两种常见的避免死锁的方法:

  1. 死锁检测算法
  2. 银行家算法

1. 死锁检测算法

死锁检测算法,首先需要一种数据结构来保存资源的请求和分配
其次是通过算法,利用请求和分配信息检测系统是否存在死锁

首先画图理解一下
【Linux】死锁(更新中)_第3张图片

如果系统中空闲的资源满足线程所需资源数量,那么该线程不会阻塞。
而当一个线程完成执行任务,将资源归还给操作系统,那么空闲的资源变多,可能使得一些本来因空闲资源不足而阻塞等待的线程被激活,开始执行任务。
以此类推,当最后所有线程都完成任务时,表面给程序没有死锁。
当一个线程可以完成任务时,我们可以在图中将其有向边消除。比如P1完成任务。

【Linux】死锁(更新中)_第4张图片
然后再P2完成任务
【Linux】死锁(更新中)_第5张图片

所有有向边消除,表面该程序没有死锁。


但如果是以下场景
【Linux】死锁(更新中)_第6张图片

R1分配2个资源给P1,分配1个资源给P2,R2分配1个资源给P2,但是此时,P2需要两个R1资源才能开始执行任务,P1需要两个R2资源才能执行任务,两个线程互相等待资源,但又不释放自己分配到的资源,导致死锁。

检测死锁的算法

在资源分配图中,找到既不阻塞又不是孤点的线程Pi(即找出一条有向边与它相连,且该有向边对应资源的申请数量小于等于系统中已有空闲资源数量。若所有链接该线程的有向边都满足次条件,那么该线程可以执行任务,然后归还资源。)

然后线程Pi归还的资源可能唤醒其他线程执行任务,当最后所有有向边都消除了,那么该程序没有死锁,反之,剩下的有向边是导致死锁的原因之一。


2. 银行家算法

后续补充

结束语

感谢你的阅读

如果觉得本篇文章对你有所帮助的话,不妨点个赞支持一下博主,拜托啦,这对我真的很重要。
在这里插入图片描述

你可能感兴趣的:(Linux学习笔记,jvm,开发语言,c++)