Synchronized死锁
测试代码
/*** 死锁测试*/@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
,并继续执行,调用u1的sub
方法,在sub
方法中同样使用synchronized 对代码块进行了加锁,此时的A线程准备拿LOCK-4
因为B线程自己的hit
方法没有执行完,锁还未释放,所以进入等待状态,B线程拿到时间片获得执行权,同样B线程要拿到u1对应的LOCK-3
,因为前边A线程在执行hit
方法时,已经拿到LOCK-3
,并且在执行u1的sub
方法时阻塞,导致hit
方法没有执行完毕,无法释放锁LOCK-3
.
因为互相持有对方想要的锁,并且想要拿到对方持有的锁,导致谁也无法拿到锁,无法继续往下执行并且释放锁
图解
如何避免发生死锁
- 以上边的demo为例子可以避免
Synchronized
修饰的方法嵌套调用 - 对每个方法使用单独的锁对象
- 降低
Synchronized
的锁的范围
Synchronized死锁相关推荐
- synchronized锁的基本用法
在多线程的情况下 需要是同一个对象锁 Synchronized(对象锁) { 需要保证线程安全的代码 } 1.修饰代码块,指定加锁对象,对给定对象加锁,进入同步代码快前要获得 给定对象 的锁. 2.修 ...
- 多线程Synchronized锁的使用与线程之间的通讯
多线程Synchronized锁的使用与线程之间的通讯 一.什么是线程安全问题 二.如何解决线程安全问题 三.synchronized锁的基本用法 1.修饰代码块(this锁) 2.修饰实例方法(th ...
- JAVA面试题解惑系列(十)——话说多线程
JAVA面试题解惑系列(十)--话说多线程 关键字: java 面试题 多线程 thread 线程池 synchronized 死锁 作者:臧圩人(zangweiren) 网址:http://zang ...
- 关于多线程中的面试题
关于多线程中的面试题 常见面试的 1.现在有T1.T2.T3三个线程,你怎样保证T2在T1执行完后执行,T3在T2执行完后执行? 答:使用join就OK了. public class ThreeThr ...
- 8w字 | Java并发编程 全套功法
介绍:CSDN统计字数:77153字,Java多线程从入门到精通,由浅入深.[建议收藏!] ❤️❤️❤️❤️❤️❤️ 点击主页发现更多好文❤️❤️❤️❤️❤️❤️ 文章目录 引言 什么是进程,线程? ...
- 计算机操作系统(详细)
分级机制 非常重要 比较重要 一般重要 第一章(概述) 作为用户和计算机硬件之间的接口 提供的功能 命令接口 联机命令接口:说一句做一句 脱机命令接口:说一堆做一堆 程序接口:"系统调用&q ...
- 一些名词或者术语(不断补充中……)
transient volatile native static(方法,属性,代码块) 分布式锁(数据库,redis,zookeeper) 缓存(热数据和冷数据)(雪崩(大批量集体同一时刻失效),缓存 ...
- 多线程-使用大全 基础使用 / 锁 / 线程池 / 原子类 / 并发包 / CAS / AQS (2022版)
一.多线程描述 1.什么是cpu CPU的中文名称是中央处理器,是进行逻辑运算用的主要由运算器.控制器.寄存器三部分组成, 运算器:从字面意思看就是运算就是起着运算的作用, 控制器:就是负责发出cpu ...
- 3.深入理解Java并发编程
多线程相关知识 多线程的基本概念 什么是cpu CPU的中文名称是中央处理器,是进行逻辑运算用的,主要由运算器.控制器.寄存器三部分组成,从字面意思看就是运算就是起着运算的作用,控制器就是负责发出cp ...
最新文章
- 深入分析ADO.NET中的DataSet对象
- yaf框架学习文件配置
- 当session失效后,无论点击那个页面,都找到顶端页面,跳到登录页面。
- leetcode346. 数据流中的移动平均值
- python爬虫源码项目_32个Python爬虫实战项目,满足你的项目慌(带源码)
- silverlight 二级导航
- 新浪微博放开140字限制:社交向左 原创向右
- python基础知识-Python基础知识
- linux基本命令示例_Linux中带示例的sort命令
- 简单利用字典破解zip文件口令
- [学习笔记-SLAM篇]视觉SLAM十四讲ch3
- 戴尔笔记本插入耳机后声音还是外放
- apk分包思路(一)meta-data
- Hinton 2006 science 文章 RBM 预训练 AutoEncoder
- 【安卓Framework学习】Wifi框架学习之热点评分机制
- MyBatis-Plus分页插件使用避坑:cannot be cast to com.baomidou.mybatisplus.core.metadata.IPage
- 计算机中的表格中怎么排序,如何设置Excel表格的横向排序功能
- 微型计算机第六章课后答案,微型计算机原理及其接口技术第六章部分习题.doc...
- java javax org_java mail程序--ClassNotFoundException:javax.mail.Address
- win7 php mysql环境,在win7下搭建php+apache+mysql环境
热门文章
- ERROR: AddressSanitizer: odr-violation ord 错误
- MySQL 数据库表的设计
- 轩小陌的Python笔记-day15 内置模块(剩余)和开发规范
- POJ2010 Moo University - Financial Aid 优先队列
- java fusioncharts_FusionCharts的使用总结(java)
- 深圳威锋网前端面试总结
- Sage X3 ERP如何帮助客户提高库存盘点准确率仓库为什么要多次盘点?
- 基石为勤能补拙的迷宫之旅——第五天(Python基本数据类型及内置方法)
- 基于.NET实现的家电维修保养信息系统[含文档+PPT+源码等]精品
- jQuery Mobile的安装