什么是线程死锁

线程死锁是指由于两个或者多个线程互相持有对方所需要的资源,导致这些线程处于相互等待状态,若无外力作用,它们将无法继续执行下去。

造成死锁的原因可以概括成三句话:

  • 当前线程拥有其他线程需要的资源
  • 当前线程等待其他线程已拥有的资源
  • 不放弃自己拥有的资源

线程死锁产生的四个必要条件

  1. 互斥,共享资源 X 和 Y 只能被一个线程占用;
  2. 占有且等待,线程 T1 已经取得共享资源 X,在等待共享资源 Y 的时候,不释放共享资源 X;
  3. 不可抢占,其他线程不能强行抢占线程 T1 占有的资源;
  4. 循环等待,线程 T1 等待线程 T2 占有的资源,线程 T2 等待线程 T1 占有的资源,就是循环等待。

举个必然产生死锁的例子

public static void main(String[] args) {Object a = new Object();Object b = new Object();// 线程1new Thread(() -> {synchronized (a) {System.out.println("获得了A锁");try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}synchronized (b) {}}}).start();// 线程2new Thread(() -> {synchronized (b) {System.out.println("获得了B锁");try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}synchronized (a) {}}}).start();
}

上面的程序就是一个典型死锁的例子,为了保证死锁发生的几率,我这里在获得锁之后睡眠了1s。

线程1在获得A对象锁之后等了1s去尝试获取B对象锁,这时线程1是持有A对象锁的;线程2在获得B对象锁之后等待1s去尝试获得A对象锁,这时线程2是持有B对象锁的;就在它们彼此想获得对方的锁的时候,死锁发生了,并且一直持续下去。

如何避免死锁

上面提到只有这四个条件都发生时才会出现死锁,那么意思就是说,只要我们破坏其中一个,就可以成功预防死锁的发生。

  • 破坏互斥:只有一把锁,这是形成死锁的最关键的原因。显然,如果我们能在两个线程跑之前,能给每个线程单独拷贝一份钥匙的副本,就能有效的避免死锁了。
  • 占用且等待一次性申请所有的资源,这样就不存在等待了。
    例如线程1一次性拿到A和B两个锁,线程2在获取锁的时候需要等待线程1释放锁,这样就避免了多线程互相占用等待的情况。
  • 不可抢占:占用部分资源的线程进一步申请其他资源时,如果申请不到,可以主动释放它占有的资源。
    在上面的死锁代码中,我们使用了synchronized关键字,它是不能主动释放资源的,会造成线程一直阻塞,JUC提供了Lock解决这个问题。
    显式使用Lock类中的定时tryLock功能来代替内置锁机制,可以检测死锁和从死锁中恢复过来。显式锁可以指定一个超时时限(Timeout),在等待超过该时间后tryLock就会返回一个失败信息,释放其拥有的资源,其他线程可以获取此资源避免死锁。
  • 循环等待:如果一个线程需要一些锁,那么它必须按照确定的顺序获取锁。只有先获得了从顺序上排在前面的锁之后,才能获取后面的锁。
    破坏循环条件很简单,只要线程之间不要出现交叉占用的情况即可,也就是说在在代码中尽量避免线程1保持A请求B,线程2保持B请求A,尽可能使他们请求的顺序一致,比如线程1请求的顺序是A、B,线程2请求的顺序也是A、B,这样自然就避免了循环等待的情况发生。

总结

死锁是一个比较头疼的问题,但是只要我们的代码规范,可以避免大多数情况下的死锁。还有避免死锁的经典算法是银行家算法,这里就不扩开介绍了。

在很多情况下,尤其是多线程编程中,我们要注意线程之间的资源是否存在互相竞争的情况,如果有,要及时规避死锁的风险。

死锁很多时候会发生在数据库操作中,例如长事务、并发条件下的共享锁升级等都会造成数据库死锁,后面有时间会专门针对数据库死锁讲一讲。

线程死锁——死锁产生的条件相关推荐

  1. Linux 多线程(二)线程安全:线程安全、互斥与互斥锁、死锁、同步与条件变量

    线程安全 互斥 死锁 同步 线程安全 所谓线程安全,其实就是当多个线程对临界资源进行争抢访问的时,不会造成数据二义或者逻辑混乱的情况(通常情况下对全局变量和静态变量进行操作时在会出现) 常见的线程安全 ...

  2. 关于操作系统中进程、线程、死锁、同步、进程间通信(IPC)的超详细详解整理

    ​​​​​​​作者主页:https://www.zhihu.com/people/san-hao-bai-du-ren-79 一.什么是进程?什么是线程? 1.1 进程定义 1.2 线程定义 1.3 ...

  3. Java线程的死锁和活锁

    文章目录 1.概览 2.死锁 2.1.什么是死锁 2.2 死锁举例 2.3 避免死锁 3.活锁 3.1 什么是活锁 3.2 活锁举例 3.3 避免活锁 1.概览 当多线程帮助我们提高应用性能的同时,它 ...

  4. 【操作系统学习笔记】—— 【二】进程、线程、死锁

    本文参考: JavaGuide 王道考研-操作系统 CS-Notes 文章目录 一.进程的概念.组成.特征 1. 概念 2. 进程的组成 PCB 程序段 数据段 3. 进程的特征 二.进程的状态 三. ...

  5. 黄金2:行稳致远-如何让你的线程免于死锁

    欢迎来到<并发王者课>,本文是该系列文章中的第12篇. 在上篇文章中,我们介绍了死锁的概念及其原因,本文将为你介绍的是几种常见的死锁预防策略. 简单来说,预防死锁主要有三种策略: 顺序化加 ...

  6. java线程饥饿死锁_java并发-线程饥饿死锁测试

    线程饥饿死锁 <Java并发编程实践>中对线程饥饿死锁的解释是这样的:在使用线程池执行任务时,如果任务依赖于其他任务,那么就可能产生死锁问题.在单线程的Executor中,若果一个任务将另 ...

  7. linux线程(互斥锁、条件)

    线程概念: 典型的UNIX/Linux进程可以看成只有一个控制线程:一个进程在同一时刻只做一件事情.有了多个控制线程后,在程序设计时可以把进程设计成在同一时刻做不止一件事,每个线程各自处理独立的任务. ...

  8. 死锁——什么是死锁 死锁的四个必要条件 避免死锁

    1 什么是死锁 死锁的定义是:在一个进程组内,每个进程都在等待只有其他进程才能引发的事件,那么该进程组处于死锁状态. 有两个线程(或者更多的线程),每个线程都在等待被其他线程占用的资源. 比如:线程A ...

  9. 分享:python,限制任意函数,线程的执行时间或根据条件终止.

    python,限制任意函数,线程的执行时间或根据条件终止. http://my.oschina.net/u/1024140/blog/122778

最新文章

  1. 旷视MegEngine核心技术升级
  2. 网络安全界永恒不变的10大安全法则
  3. 【深度学习】Tensorflow搭建卷积神经网络实现情绪识别
  4. 《Python数据科学指南》——1.16 使用lambda创造匿名函数
  5. linux nvidia 361.run,Ubuntu 16.04安装nVidia驱动失败!
  6. BaseAdapter的ArrayIndexOutOfBoundsException
  7. 22. jQuery 遍历 - 同胞
  8. Echarts 下载使用教程
  9. tspline工具_TSpline2.0海豚建模教程.pdf
  10. iPhone X 不充电维修案例
  11. 数据结构——“双向循环链表“ 易懂刨析双向循环链表(图解+代码)
  12. php批量邮件地址,PHP通过phpmailer批量发送邮件功能
  13. ckfinder 配置 php,CKEditor4+CKFinder3(php版本)安装及配置方法
  14. 【SEED Labs 2.0】Packet Sniffing and Spoofing Lab
  15. latex tex studio 表格大小 整体缩小 过长 过宽 跨栏 跨页
  16. Data()笔记之getDay()的基本用法
  17. 1.C语言变量类型、全局变量、局部变量
  18. 通过改变电脑的某些设置来呵护我们的眼睛
  19. 《实时控制软件设计》第一次编程作业
  20. 雌雄异体,伴X染色体的等位基因(2个),计算子代的基因型频率

热门文章

  1. layui使用tips_layui的tips层怎么用?
  2. TX2进入Recover恢复模式
  3. 百亿级图数据在快手安全情报的应用与挑战
  4. 海航exchange邮箱服务器,Exchange 邮件系统
  5. MP3文件信息编辑利器 - Mp3tag
  6. springboot整合shiro(超详细,你想要的都在这了)
  7. setpercision(n) setiosflags(ios::fixed) setiosflags(ios::scientific)
  8. 计算机怎么填接新的网络,新电脑怎么设置网络连接
  9. DatabaseMetaData查询集群下的库名
  10. html做静夜思加css样式,HTML+CSS网页设计_图文.ppt