一、什么是死锁

简单理解就是:一个线程加锁之后,无法被解锁,导致程序无法正常运行。

二、死锁的成因

1、一个线程,一把锁的情况

一个线程连续加锁两次,如果这个锁是不可重入锁,那么一定会死锁

synchronized可重入锁,所以不会有这个问题~

2、两个线程,两把锁的情况

死锁场景:线程1先获取锁A,再尝试获取锁B,同时,线程2先获取锁B,再尝试获取锁A,此时两个线程就会互相僵住,谁都获取不到对方持有的锁。

一个简单的死锁代码:

public class Test {public static void main(String[] args) {//2个锁对象Object lockerA = new Object();Object lockerB = new Object();Thread t1 = new Thread(() -> {System.out.println("t1尝试获取锁A");synchronized (lockerA){System.out.println("t1获取到锁A");try {Thread.sleep(100);} catch (InterruptedException e) {e.printStackTrace();}System.out.println("t1尝试获取锁B");synchronized (lockerB){System.out.println("t1获取到锁B");}}});Thread t2 = new Thread(() -> {System.out.println("t2尝试获取锁B");synchronized (lockerB){System.out.println("t2获取到锁B");try {Thread.sleep(100);} catch (InterruptedException e) {e.printStackTrace();}System.out.println("t2尝试获取锁A");synchronized (lockerA){System.out.println("t2获取到锁A");}}});t1.start();t2.start();}
}

代码运行结果:

因为锁A当前被t1所持有,锁B当前被t2所持有,在两个线程都没有释放锁之前,尝试获取对方所持有的锁,那么必然会出现死锁的情况~

这就好比,你把家里的钥匙落在了车里,车钥匙又被落在了家里~

3、多个线程多把锁的情况

2个线程都可能出现死锁的情况,那么多个线程的情况下更容易出现死锁~

哲学家就餐问题就是一个经典的多个线程死锁的场景~

三、如何避免死锁

产生死锁有4个必要条件:

(1) 互斥使用。线程1拿到锁A之后,线程2在锁A被释放之前就拿不到了。

(2) 不可抢占。线程1拿到锁A之后,线程2只能等线程1释放锁A,而不能把锁A抢过来。

(3) 请求和保持。线程1拿到锁A之后,还没释放锁A就想获取锁B。

(4) 循坏等待。线程1等待线程2释放锁,线程2等待线程3释放锁,线程3等待线程1释放锁...

既然以上4个条件是产生死锁的必要条件,那么只要打破其中一个条件,就不会产生死锁了~

其中,条件1和条件2都是锁的基本特性,我们无法干预~

条件3可以改变代码的写法,让线程1释放锁A之后再释放锁B,但这样可能会改变代码的执行逻辑,因此普适性不高。

只有条件4是我们有把握打破的~

我们可以约定好加锁的顺序,比如给每个锁进行编号,在加锁的时候,先加编号小的锁,再加编号大的锁,这样就可以有效避免循坏等待了~

比如,哲学家就餐问题的解决方案:

给每根筷子进行编号,并规定,先拿编号小的筷子,后拿编号大的筷子。

如上图,E就可以先拿到2根筷子吃面,E吃完后放下筷子,D就可以获取到2根筷子,D吃完后C获取到2根筷子……这样每个哲学家都能吃到面条,而不会出现死锁的情况。

死锁的成因和解决方案相关推荐

  1. 线程死锁的成因以及解决方案

    线程死锁 一 . 什么是线程死锁 二 . 如何避免死锁 一 . 什么是线程死锁 线程死锁描述的是:多个线程同时被阻塞,他们中的一个或多个都在等待某个资源被释放,由于线程被无期限地阻塞,因此程序不可能正 ...

  2. mysql死锁解决方法_mysql出现死锁的原因及解决方案

    mysql出现死锁的原因及解决方案 发布时间:2020-06-04 16:35:40 来源:51CTO 阅读:418 作者:三月 本文主要给大家介绍mysql出现死锁的原因及解决方案,文章内容都是笔者 ...

  3. 分布式架构-ZK分布式锁中死锁和羊群效应解决方案

    分布式架构-ZK分布式锁中死锁和羊群效应解决方案 一.效果演示 有两个接口,GetTest2和GetTest3,分别都加上了@BxcZkLock注解,其中value 代表是否包含事物,如果是,则会在方 ...

  4. MySQL - 死锁的产生及解决方案

    MySQL - 死锁的产生及解决方案 1. 死锁与产生死锁的四个必要条件 1.1 什么是死锁 1.2 死锁产生的4个必要条件 2. 死锁案例 2.1 表锁死锁 2.2 行锁死锁 2.3 共享锁转换为排 ...

  5. java排查死锁_Java死锁的排查和解决方案

    相信程序员都会碰上这样的问题,Java死锁如何排查?又如何解决呢?那么,何为死锁呢?死锁是指两个或两个以上的进程在执行过程中,由于竞争资源或者由于彼此通信而造成的一种阻塞的现象.今天小编一次性来帮助大 ...

  6. 死锁的成因和对应的解决方案

    目录 一.什么是死锁 二.产生死锁的三个典型场景

  7. 【多线程】并发死锁问题与企业级解决方案

    1. 死锁是什么?有什么危害 1.1 什么是死锁 发生在并发种 互不相让:当两个(或更多)线程(或进程)相互持有对方所需要的资源,又不主动释放,导致所有人都无法继续前进,导致程序陷入无尽的阻塞,这就是 ...

  8. Java 程序死锁问题原理及解决方案

    原文出处: IBM developerWorks Java 语言通过 synchronized 关键字来保证原子性,这是因为每一个 Object 都有一个隐含的锁,这个也称作监视器对象.在进入 syn ...

  9. 线程死锁的成因?如何查找并定位死锁,解决死锁?这里教你几招~

    目录 什么是死锁? 死锁代码案例: 出现死锁的原因 教你如何定位死锁位置~ 死锁解决方法 什么是死锁? 死锁就是指线程t1要使用的资源被线程t2占用,线程t2想使用的资源被线程 t1占用,这就像两股绳 ...

最新文章

  1. Tungsten Fabric SDN — 软件架构
  2. 【Java】判断字符串是否含字母
  3. BW事务代码SXMB_ADM、 SICF、SMICM简介
  4. Unix Shell 数学计算命令
  5. 光纤测试仪为什么使用单芯法为光纤损耗测量
  6. IE8 beta2现已正式发布!
  7. 龙族幻想服务器维护中怎么办,龙族幻想遇到无法连接服务器?两招教你轻松解决...
  8. velocity 时间显示 时间格式化 时间转化
  9. 进程queue和线程queue
  10. 台安变频器n2按键说明_台安变频器N2
  11. Android 查看是否支持指定解码器(H265)
  12. 吴伯凡-认知方法论-如何增加自己认知的维度
  13. kali linux怎么安装无线网卡驱动,Kali Linux 安装BCM43142网卡驱动
  14. Unity http协议连接封装简易版(已测试可用)
  15. 帝国CMS模板组创建和管理,让网站完成迅速”变脸“
  16. 【2.5万字】详解 Python-docx 自动生成word图文报告
  17. linux v4l2系统详解,Linux摄像头驱动学习之:(一)V4L2_框架分析
  18. x86架构下的安卓虚拟化
  19. 2.6.36.2 s3c6410 触摸屏驱动移植。
  20. [LeetCode]682. 棒球比赛(Baseball Game)Java

热门文章

  1. 多旋翼油门量与升力关系
  2. 兴趣变高薪副业,知名插画师走尺带你感受插画的魅力
  3. 提升学习 Prompt 总结
  4. Scala 继承和特质
  5. python标准数据类型叮叮叮
  6. 绘画入门经典教程——如果你想, 一切皆有可能!
  7. asp.net动态网页制作视频教程
  8. 如何培养员工的团队合作精神
  9. Payment:支付宝即时到账接口接入教程
  10. 关于const A* f(const A* pSrc,A* const pDst,int v=2,...) const throw();