测试代码

/*** 死锁测试*/@Testvoid deadLockTests() throws InterruptedException {for (int i = 0; i < 100000; i++) {User u1 = new User(50);User u2 = new User(50);log.info("第 - {} - 次",i);Thread thread = new Thread(() -> {u1.hit(u2);},"A");Thread thread1 = new Thread(() -> {u2.hit(u1);},"B");thread1.start();thread.start();thread1.join();thread.join();}}private static int i = 0;static class User{public int num;private final Lock lock = new Lock(++i);public User(int num) {this.num = num;}public void sub(int step){log.info("我是{} 我的锁是: {} ,我准备拿sub锁 {} ",Thread.currentThread().getName(),lock,lock);synchronized (lock){log.info("我是{} 拿到的sub锁为: {}",Thread.currentThread().getName(),lock);this.num = this.num - step;}log.info("我是{} 我的锁是: {} 我释放了sub锁:{}",Thread.currentThread().getName(),lock,lock);}public void hit(User user){log.info("我是{} 我的锁是: {},我准备拿hit锁 {} ",Thread.currentThread().getName(),lock,lock);synchronized (lock){log.info("我是{} 拿到hit锁的锁为: {}",Thread.currentThread().getName(),lock);if (user != null){user.sub(10);}}log.info("我是{} 我的锁是: {},我释放了hit锁 {} ",Thread.currentThread().getName(),lock,lock);}}static class Lock{private final int i;Lock(int i) {this.i = i;}@Override public String toString() {return "LOCK-"+i;}}

输出结果

在这里插入图片描述

17:18:53.921 [main] INFO com.yunju.demo.Tests - 第 - 0 - 次
17:18:53.924 [B] INFO com.yunju.demo.Tests - 我是B 我的锁是: LOCK-2,我准备拿hit锁 LOCK-2
17:18:53.929 [B] INFO com.yunju.demo.Tests - 我是B 拿到hit锁的锁为: LOCK-2
17:18:53.929 [B] INFO com.yunju.demo.Tests - 我是B 我的锁是: LOCK-1 ,我准备拿sub锁 LOCK-1
17:18:53.930 [B] INFO com.yunju.demo.Tests - 我是B 拿到的sub锁为: LOCK-1
17:18:53.924 [A] INFO com.yunju.demo.Tests - 我是A 我的锁是: LOCK-1,我准备拿hit锁 LOCK-1
17:18:53.930 [B] INFO com.yunju.demo.Tests - 我是B 我的锁是: LOCK-1 我释放了sub锁:LOCK-1
17:18:53.930 [A] INFO com.yunju.demo.Tests - 我是A 拿到hit锁的锁为: LOCK-1
17:18:53.930 [B] INFO com.yunju.demo.Tests - 我是B 我的锁是: LOCK-2,我释放了hit锁 LOCK-2
17:18:53.930 [A] INFO com.yunju.demo.Tests - 我是A 我的锁是: LOCK-2 ,我准备拿sub锁 LOCK-2
17:18:53.930 [A] INFO com.yunju.demo.Tests - 我是A 拿到的sub锁为: LOCK-2
17:18:53.930 [A] INFO com.yunju.demo.Tests - 我是A 我的锁是: LOCK-2 我释放了sub锁:LOCK-2
17:18:53.930 [A] INFO com.yunju.demo.Tests - 我是A 我的锁是: LOCK-1,我释放了hit锁 LOCK-1
17:18:53.931 [main] INFO com.yunju.demo.Tests - 第 - 1 - 次
17:18:53.931 [B] INFO com.yunju.demo.Tests - 我是B 我的锁是: LOCK-4,我准备拿hit锁 LOCK-4
17:18:53.931 [A] INFO com.yunju.demo.Tests - 我是A 我的锁是: LOCK-3,我准备拿hit锁 LOCK-3
17:18:53.931 [A] INFO com.yunju.demo.Tests - 我是A 拿到hit锁的锁为: LOCK-3
17:18:53.931 [B] INFO com.yunju.demo.Tests - 我是B 拿到hit锁的锁为: LOCK-4
17:18:53.931 [A] INFO com.yunju.demo.Tests - 我是A 我的锁是: LOCK-4 ,我准备拿sub锁 LOCK-4
17:18:53.931 [B] INFO com.yunju.demo.Tests - 我是B 我的锁是: LOCK-3 ,我准备拿sub锁 LOCK-3 

为什么会发生死锁

分析输出日志中的第1次结果
A线程u1的锁为LOCK-3
B线程u2的锁为LOCK-4

由输出日志可以看出B线程优先执行,B线程的u2进入hit方法,准备拿到自己对应的锁LOCK-4,在这时A线程拿到时间片开始执行,注意此时的B线程未拿到自己对应的LOCK-4,A线程同样准备拿自己的hit方法的锁,幸运的是在这时A没有被打断执行,拿到了自己的LOCK-3,接下来B线程拿到时间片开始执行,拿到了自己该拿到的LOCK-4,并继续执行,调用u1sub方法,在sub方法中同样使用synchronized 对代码块进行了加锁,此时的A线程准备拿LOCK-4因为B线程自己的hit方法没有执行完,锁还未释放,所以进入等待状态,B线程拿到时间片获得执行权,同样B线程要拿到u1对应的LOCK-3,因为前边A线程在执行hit方法时,已经拿到LOCK-3,并且在执行u1sub方法时阻塞,导致hit方法没有执行完毕,无法释放锁LOCK-3.
因为互相持有对方想要的锁,并且想要拿到对方持有的锁,导致谁也无法拿到锁,无法继续往下执行并且释放锁

图解

如何避免发生死锁

  1. 以上边的demo为例子可以避免Synchronized修饰的方法嵌套调用
  2. 对每个方法使用单独的锁对象
  3. 降低Synchronized的锁的范围

Synchronized死锁相关推荐

  1. synchronized锁的基本用法

    在多线程的情况下 需要是同一个对象锁 Synchronized(对象锁) { 需要保证线程安全的代码 } 1.修饰代码块,指定加锁对象,对给定对象加锁,进入同步代码快前要获得 给定对象 的锁. 2.修 ...

  2. 多线程Synchronized锁的使用与线程之间的通讯

    多线程Synchronized锁的使用与线程之间的通讯 一.什么是线程安全问题 二.如何解决线程安全问题 三.synchronized锁的基本用法 1.修饰代码块(this锁) 2.修饰实例方法(th ...

  3. JAVA面试题解惑系列(十)——话说多线程

    JAVA面试题解惑系列(十)--话说多线程 关键字: java 面试题 多线程 thread 线程池 synchronized 死锁 作者:臧圩人(zangweiren) 网址:http://zang ...

  4. 关于多线程中的面试题

    关于多线程中的面试题 常见面试的 1.现在有T1.T2.T3三个线程,你怎样保证T2在T1执行完后执行,T3在T2执行完后执行? 答:使用join就OK了. public class ThreeThr ...

  5. 8w字 | Java并发编程 全套功法

    介绍:CSDN统计字数:77153字,Java多线程从入门到精通,由浅入深.[建议收藏!] ❤️❤️❤️❤️❤️❤️ 点击主页发现更多好文❤️❤️❤️❤️❤️❤️ 文章目录 引言 什么是进程,线程? ...

  6. 计算机操作系统(详细)

    分级机制 非常重要 比较重要 一般重要 第一章(概述) 作为用户和计算机硬件之间的接口 提供的功能 命令接口 联机命令接口:说一句做一句 脱机命令接口:说一堆做一堆 程序接口:"系统调用&q ...

  7. 一些名词或者术语(不断补充中……)

    transient volatile native static(方法,属性,代码块) 分布式锁(数据库,redis,zookeeper) 缓存(热数据和冷数据)(雪崩(大批量集体同一时刻失效),缓存 ...

  8. 多线程-使用大全 基础使用 / 锁 / 线程池 / 原子类 / 并发包 / CAS / AQS (2022版)

    一.多线程描述 1.什么是cpu CPU的中文名称是中央处理器,是进行逻辑运算用的主要由运算器.控制器.寄存器三部分组成, 运算器:从字面意思看就是运算就是起着运算的作用, 控制器:就是负责发出cpu ...

  9. 3.深入理解Java并发编程

    多线程相关知识 多线程的基本概念 什么是cpu CPU的中文名称是中央处理器,是进行逻辑运算用的,主要由运算器.控制器.寄存器三部分组成,从字面意思看就是运算就是起着运算的作用,控制器就是负责发出cp ...

最新文章

  1. 深入分析ADO.NET中的DataSet对象
  2. yaf框架学习文件配置
  3. 当session失效后,无论点击那个页面,都找到顶端页面,跳到登录页面。
  4. leetcode346. 数据流中的移动平均值
  5. python爬虫源码项目_32个Python爬虫实战项目,满足你的项目慌(带源码)
  6. silverlight 二级导航
  7. 新浪微博放开140字限制:社交向左 原创向右
  8. python基础知识-Python基础知识
  9. linux基本命令示例_Linux中带示例的sort命令
  10. 简单利用字典破解zip文件口令
  11. [学习笔记-SLAM篇]视觉SLAM十四讲ch3
  12. 戴尔笔记本插入耳机后声音还是外放
  13. apk分包思路(一)meta-data
  14. Hinton 2006 science 文章 RBM 预训练 AutoEncoder
  15. 【安卓Framework学习】Wifi框架学习之热点评分机制
  16. MyBatis-Plus分页插件使用避坑:cannot be cast to com.baomidou.mybatisplus.core.metadata.IPage
  17. 计算机中的表格中怎么排序,如何设置Excel表格的横向排序功能
  18. 微型计算机第六章课后答案,微型计算机原理及其接口技术第六章部分习题.doc...
  19. java javax org_java mail程序--ClassNotFoundException:javax.mail.Address
  20. win7 php mysql环境,在win7下搭建php+apache+mysql环境

热门文章

  1. ERROR: AddressSanitizer: odr-violation ord 错误
  2. MySQL 数据库表的设计
  3. 轩小陌的Python笔记-day15 内置模块(剩余)和开发规范
  4. POJ2010 Moo University - Financial Aid 优先队列
  5. java fusioncharts_FusionCharts的使用总结(java)
  6. 深圳威锋网前端面试总结
  7. Sage X3 ERP如何帮助客户提高库存盘点准确率仓库为什么要多次盘点?
  8. 基石为勤能补拙的迷宫之旅——第五天(Python基本数据类型及内置方法)
  9. 基于.NET实现的家电维修保养信息系统[含文档+PPT+源码等]精品
  10. jQuery Mobile的安装