线程死锁问题以及简单案例分析

  • 1. 什么是死锁?
    • 1.1 概述
    • 1.2. 业务场景——举例说明
  • 2. 死锁例子
    • 2.1 代码
    • 2.2 效果
    • 2.3 代码分析
  • 3. 解决案例中死锁问题
  • 4. 怎么避免线程死锁?

1. 什么是死锁?

1.1 概述

  • 不同的线程分别占用对方需要的同步资源不放弃,都在等待对方放弃自己需要的同步资源,就形成了线程死锁。
  • 出现死锁后,不会出现异常,不会出现提示,只是所有的线程都处于阻塞状态,无法继续!

1.2. 业务场景——举例说明

  • 举例说明:
    比如两个小情侣刚开始感情很好,还弄了一个公共财神卡,算是个不小数额的公共资产吧,为了防止一方乱花钱,假如他们有个约定,女朋友管密码,男朋友管卡,就这样一直相处很好……

    终于有一天,两人还是产生了摩擦,简直要闹分手了,这时心里都有了一个很坏的想法,嗯,对,就是它!取钱!哈哈哈……

    欸,来到了银行,一个没密码一个没卡,嗯,尴尬,女朋友取钱的线程里的一把锁(银行卡)被男朋友握着不放,取不了钱。而那朋友又拿着那朋友取钱的那个线程里的密码锁,嗯,男朋友也取不了钱。所以,两人就冷战了,两个取钱的线程就僵在这里了,也不报错,但也执行不下去了……

    哈哈哈……我只是打个比方,你可别当真,别回去就分家产去了……

    算了,要不咱把故事画个句号吧,不然搞得怪怪的哈,故事和程序的区别是,故事遇到打雷下雨了,把两人打醒了,开始沟通互相理解吧,思想上停止取钱了,程序是你给程序停了!哈哈哈……

2. 死锁例子

2.1 代码

  • 案例就是我们上面介绍的场景例子,用代码表示如下:
package com.liu.susu.thread.deadlock;/*** @FileName DeadLockTest* @Description* @Author susu* @date 2022-03-05**/
public class DeadLockTest {public static void main(String[] args) {DrawMoney drawMoney = new DrawMoney(new Person("1", "男朋友"));DrawMoney drawMoney2 = new DrawMoney(new Person("0", "女朋友"));new Thread(drawMoney).start();new Thread(drawMoney2).start();}
}class DrawMoney implements Runnable{private static Object password = new Object();//注意是staticprivate static Object bankCard = new Object();//注意是staticprivate Person person;public DrawMoney(Person person) {this.person = person;}@Overridepublic void run() {if ("1".equals(person.sex)){//男朋友要取钱synchronized (bankCard){System.out.println(person.name+"-->只有银行卡要取钱……");try {Thread.sleep(100);} catch (InterruptedException e) {e.printStackTrace();}synchronized (password){System.out.println(person.name+"-->猜到了密码继续取钱……");}}}else {//女朋友要取钱synchronized (password){System.out.println(person.name+"-->只有密码要取钱……");try {Thread.sleep(100);} catch (InterruptedException e) {e.printStackTrace();}synchronized (bankCard){System.out.println(person.name+"-->想办法拿到银行卡继续取钱……");}}}}
}class Person{String sex;//0:女  1:男String name;public Person(String sex,String name){this.sex=sex;this.name=name;}
}
  • 注意点:
    两个取钱线程 new DrawMoney两个,所以注意那两把锁要是静态的共享资源,不然模拟不出来

2.2 效果

  • 如下图:程序会卡在这里不动……

2.3 代码分析

  • 看图说话:

  • 我们看到是同步代码块儿里嵌到同步代码,女朋友的一样。

    这里有两把锁,一个是银行卡锁,一个是密码锁,两个取钱线程共享这两把锁。

    男孩先进来拿到银行卡的锁,这个代码块不执行完,银行卡的锁释放不了,而在这个代码块里他要想取钱还有获得密码锁,不然取不了钱,释放不了银行卡锁;但是此时密码锁被女孩的线程拿着,女孩线程要想取钱还有获得银行卡锁,不然也释放不了密码锁。所以两个线程都结束不了……

3. 解决案例中死锁问题

  • ① 如果对于代码上,我们把静态资源 password 和 bankCard 设置为非静态的可以避免出现死锁,但是这样设置两个线程就不是同一把锁了,你可以理解为两人取钱拿的不是同一个卡,就不是我们上面的业务场景了。
  • ② 既然是同步代码块儿的嵌套造成的死锁,那我们就不嵌套不就可以了嘛,如图:
  • 修改后的代码:
package com.liu.susu.thread.deadlock;/*** @FileName DeadLockTest* @Description* @Author susu* @date 2022-03-05**/
public class DeadLockTest {public static void main(String[] args) {DrawMoney drawMoney = new DrawMoney(new Person("1", "男朋友"));DrawMoney drawMoney2 = new DrawMoney(new Person("0", "女朋友"));new Thread(drawMoney).start();new Thread(drawMoney2).start();}
}class DrawMoney implements Runnable{private  static Object password = new Object();//注意是staticprivate  static Object bankCard = new Object();//注意是staticprivate Person person;public DrawMoney(Person person) {this.person = person;}@Overridepublic void run() {if ("1".equals(person.sex)){//男朋友要取钱synchronized (bankCard){System.out.println(person.name+"-->只有银行卡要取钱……");try {Thread.sleep(100);} catch (InterruptedException e) {e.printStackTrace();}}synchronized (password){System.out.println(person.name+"-->猜到了密码继续取钱……");}}else {//女朋友要取钱synchronized (password){System.out.println(person.name+"-->只有密码要取钱……");try {Thread.sleep(100);} catch (InterruptedException e) {e.printStackTrace();}}synchronized (bankCard){System.out.println(person.name+"-->想办法拿到银行卡继续取钱……");}}}
}class Person{String sex;//0:女  1:男String name;public Person(String sex,String name){this.sex=sex;this.name=name;}
}
  • 修改后的效果:

4. 怎么避免线程死锁?

  • 尽量避免嵌套同步
  • 尽量减少同步资源的定义
  • 专门的算法,原则

这个有篇文章写的不错,可以看看:
多线程之死锁详解.

线程死锁问题以及简单案例分析相关推荐

  1. led HAL简单案例分析

    mr_raptor的专栏 专注Android系统,移动平台研究,ARM BSP开发,著有<深入浅出嵌入式底层软件开发>北航出版社 目录视图 摘要视图 订阅 CSDN Android客户端 ...

  2. Android 线程死锁导致的ANR问题分析

    最近遇到一个系统引起的ANR问题,遇到的时候特别懵,首先我取出了日志文件,由于网上分析ANR的例子比较少,无法找到参考,所以只能硬上了 在/data/anr/目录下的trace文件 ANR文件 下面是 ...

  3. vs2013配置OpenGL+简单案例分析

    一.安装 我的系统是win10 64位,用的是visual studio2013,vs装在了E盘下面. ------------------------------------------------ ...

  4. 在dos中分析线程死锁堆栈消息的案例----用Thread简单Demo,教会你如何分析堆栈消息

    欢迎加群:854228077. 帮助更多java程序员提升技术!资料多,大佬多! java代码如下: package com.rh.chapter_four;/*** @author :pan_zho ...

  5. Java分析系列之五:常见的Thread Dump日志案例分析

    我们在上篇文章中详细描述了Thread Dump中Native Thread和JVM Thread线程的各种状态及描述,今天总结分析的一些原则,并详细列举一些案例进行说明. 目录 [隐藏] 1 症状及 ...

  6. Log4j线程死锁–案例研究

    此案例研究描述了影响Weblogic Portal 10.0生产环境的Apache Log4j线程争用问题的完整根本原因分析和解决方案. 它还将说明在开发和支持Java EE应用程序时适当的Java类 ...

  7. 《手Q Android线程死锁监控与自动化分析实践》

    一.问题背景 手Q每个版本上线以后研发同学都会收到各种问题反馈.在跟进手Q内部用户反馈的问题时,发现多例问题,其表象和原因如下: 1.问题表象:"未读不消失"."图片不展 ...

  8. 45.JVM调优策略、常见问题:内存泄漏(年老代堆空间被占满、持久代被占满、堆栈溢出、线程堆栈满、系统内存被占满)优化方法:优化目标、优化GC步骤、优化总结;案例分析(公司系统参数、网上给的配置参数)

    45.JVM调优策略 45.1.常见问题 45.1.1.内存泄漏 45.1.1.1.年老代堆空间被占满 45.1.1.2.持久代被占满 45.1.1.3.堆栈溢出 45.1.1.4.线程堆栈满 45. ...

  9. JAVA笔记14__多线程共享数据(同步)/ 线程死锁 / 生产者与消费者应用案例 / 线程池...

    /*** 多线程共享数据* 线程同步:多个线程在同一个时间段只能有一个线程执行其指定代码,其他线程要等待此线程完成之后才可以继续执行.* 多线程共享数据的安全问题,使用同步解决.* 线程同步两种方法: ...

最新文章

  1. java调用本地shell_java通过ProcessBuilder执行本地shell命令 获取ip配置信息
  2. jax-rs/jersey_在Oracle Cloud上的Prime-UI,JAX-RS和Jersey和Gson
  3. 解决在html中引入font-awesome的css文件后, 图标显示不出来
  4. element手机验证格式_vue封装 element-ui form表单验证 正则匹配手机号 自定义校验表格内容...
  5. 利用JavaScript制作星星金字塔
  6. python中classmethod与staticmethod的差异及应用
  7. 一行代码扫出“敬业福”
  8. 视频压缩编码基础知识(上)
  9. SQL Server游标使用快速上手
  10. 苹果手机充电口接触不良怎么办_用了HOU吼猴3C数码配件让手机充电口不再接触不良...
  11. scikit-learn:回归分析—一元非线性回归
  12. 锐意创新,引领音视频未来
  13. 产业区块链一周动态丨江西将出台区块链五年计划,数字货币试点引发A股躁动...
  14. 服务器返回的常见http状态码
  15. java poi写入excel_Java使用POI读取和写入Excel指南
  16. CMD设置代理 注册表设置IE代理
  17. 记嵌入式硬件开发实习
  18. Jamie's Contact Groups ——(一对多)二分图多重最大匹配
  19. python爬虫获取起点中文网人气排行Top100(快速入门,新手必备!)
  20. 阿里云IoT物模型-属性,服务,事件通信的topic和payload详解——设备管理运维类

热门文章

  1. python的divmod函数_python每日一函数 - divmod数字处理函数
  2. aspire鹦鹉螺_Aspire 鹦鹉螺 X 雾化器使用评测
  3. Vue中v-bind,v-on,v-model都是干什么的(区别以及详细用法)?自制动图,一看就懂 ∠( °ω°)/ 前端知识
  4. 手机+Driver4VR模拟VR一体机:解锁零成本VR游戏无线体验方案 | driver4vr破解 alyx
  5. 10亿行C ++代码使用3万元/个的电脑处理器AMD Threadripper 3990X:在64核CPU处理器256GB内存电脑上编译需要多长时间?
  6. echarts 极坐标设置分隔区域颜色
  7. Vue组件通信09-多层级组件通信(爷爷到孙子-传方法)-$listener
  8. java怎么判断json是否为空_java判断jsonObject和jsonArray是否为空
  9. oracle如何添加触发器,Oracle之前插入触发器
  10. 创新思维与实践思维导图