网易首页 > 网易号 > 正文 申请入驻

Java开发之多线程死锁问题排查与解决

0
分享至

死锁问题

死锁定义

多线程编程中,因为抢占资源造成了线程无限等待的情况,此情况称为死锁。

死锁举例

注意:线程和锁的关系是:一个线程可以拥有多把锁,一个锁只能被一个线程拥有。

当两个线程分别拥有一把各自的锁之后,又尝试去获取对方的锁,这样就会导致死锁情况的发生,具体先看下面代码:

/**
* 线程死锁问题
*/
public class DeadLock {
public static void main(String[] args) {
//创建两个锁对象
Object lock1 = new Object();
Object lock2 = new Object();
//创建子线程
/*
线程1:①先获得锁1 ②休眠1s,让线程2获得锁2 ③线程1尝试获取锁2 线程2同理
*/
Thread thread1 = new Thread(new Runnable() {
@Override
public void run() {
//线程1业务逻辑
synchronized(lock1){
System.out.println("线程1得到了锁子1");
try {
//休眠1s,让线程2先得到锁2
Thread.sleep(1000);
{ catch (InterruptedException e) }
e.printStackTrace();
}
System.out.println("线程1尝试获取锁2...");
synchronized(lock2){
System.out.println("线程1获得了锁2!");
}
}
}
},"线程1");
Thread thread2 = new Thread(new Runnable() {
@Override
public void run() {
//线程2业务逻辑
synchronized(lock2){
System.out.println("线程2得到了锁子2");
try {
//休眠1s,让线程1先得到锁1;因为线程是并发执行我们不知道谁先执行
Thread.sleep(1000);
{ catch (InterruptedException e) }
e.printStackTrace();
}
System.out.println("线程2尝试获取锁1...");
synchronized(lock1){
System.out.println("线程2获得了锁1");
}
}
}
},"线程2");
thread1.start();
thread2.start();
}
}

程序运行结果如下:

可以看出,线程1尝试获取了锁2,线程2尝试获取了锁1,但是二者并没有获取到对方的锁;这就发生了所谓的“死锁”!

如何排查死锁

想要排查死锁具体细节,可以通过三个工具(位于jdk安装路径bin目录)去排查,现在就给大家介绍一下:

1.jconsole

可以看出,线程1和线程2发生了死锁,死锁发生的位置一目了然

2.jvisualvm

可以看出,发生了死锁,线程1和线程2尝试获取的锁是对方的锁。

3.jmc

可以看出,同样检测出了死锁情况
无论是用哪个工具排查死锁情况都是OK的。

死锁发生的条件

1.互斥条件(一个锁只能被一个线程占有,当一个锁被一个线程持有之后,不能再被其他线程持有);
2.请求拥有(一个线程拥有一把锁之后,又去尝试请求拥有另外一把锁);可以解决
3.不可剥夺(一个锁被一个线程占有之后,如果该线程没有释放锁,其他线程不能强制获得该锁);
4.环路等待条件(多线程获取锁时形成了一个环形链)可以解决

怎么解决死锁问题?

环路等待条件相对于请求拥有更容易实现,那么通过破坏环路等待条件解决死锁问题
破坏环路等待条件示意图:

针对于上面死锁举例中代码,解决死锁,具体看下面代码:

public class SolveDeadLock {
public static void main(String[] args) {
//创建两个锁对象
Object lock1 = new Object();
Object lock2 = new Object();
Thread thread1 = new Thread(new Runnable() {
@Override
public void run() {
//线程1业务逻辑
synchronized(lock1){
System.out.println("线程1得到了锁子1");
try {
Thread.sleep(1000);
{ catch (InterruptedException e) }
e.printStackTrace();
}
System.out.println("线程1尝试获取锁2...");
synchronized(lock2){
System.out.println("线程1获得了锁2!");
}
}
}
},"线程1");
Thread thread2 = new Thread(new Runnable() {
@Override
public void run() {
//线程2业务逻辑
synchronized(lock1){
System.out.println("线程2得到了锁子1");
try {
Thread.sleep(1000);
{ catch (InterruptedException e) }
e.printStackTrace();
}
System.out.println("线程2尝试获取锁2...");
synchronized(lock2){
System.out.println("线程2获得了锁2");
}
}
}
},"线程2");
thread1.start();
thread2.start();
}
}

程序运行结果如下:

可以看出,通过破坏环路等待条件完美解决了死锁问题

线程通讯机制(wait/notify/notifyAll)

定义

线程通讯机制:一个线程的动作可以让另外一个线程感知到,这就是线程通讯机制。
wait():让当前线程进入休眠等待状态;
notify():唤醒当前对象上的休眠等待线程;
notifyAll():唤醒当前对象上的所有休眠等待线程。

相关面试重点

面试问题:
1.wait()使用时为什么需要加锁?
因为wait()必须在同步方法或者同步块中使用,也就是说wait()需要配合加锁一起使用(比如synchronized或Lock),调用对象调用wait()如果没有适当的加锁,就会引发异常,因此说wait()使用时需要加锁。
2.wait()使用为什么要释放锁?
wait()是Objetc类中一个实例方法,默认是不传任何值的,不传值的时候表示让当前线程处于永久休眠等待状态,这样会造成一个锁被一个线程长时间一直拥有,为了避免这种问题的发生,使用wait()后必须释放锁。

wait()/notify()/notifyAll()使用时注意事项:
使用这三个方法时都必须进行加锁;
2.加锁的对象和调用wait()/notify()/notifyAll()对象必须是同一个对象;
3.一组wait()/notify()/notifyAll()必须是同一个对象;
4.notify()只能唤醒当前对象上的一个休眠等待线程;而notifyAll()可以唤醒当前对象上的所有休眠等待线程。

sleep(0)和wait(0)的区别:
1.sleep()是Thread类中一个静态方法,wait()是Object类中一个普通的成员方法;
2.sleep(0)会立即触发一次CPU的抢占执行,wait(0)会让当前线程无限休眠等待下去。

wait()和sleep()的区别:
相同点:
1.都会让当前线程进行休眠等待;
2.使用二者时都需处理InterruptedException异常(try/catch)。
不同点:
1.wait()是Object中普通成员方法,sleep是Thread中静态方法;
2.wait()可以使用参数,sleep()必须传入一个大于等于0的参数;
3.wait()使用时必须配合加锁一起使用,sleep()使用时不需要加锁;
4.wait()使用时需要释放锁,如果sleep()加锁后不会释放锁;
5.wait()会让当前线程进入WAITING状态(默认没有明确的等待时间,当被别的线程唤醒或者wait()传参后超过等待时间量自己唤醒,将进入就绪状态),sleep()会让当前线程进入TIMED_WAITING状态(有明确的结束等待时间,但是这是死等的方式,休眠结束后进入就绪状态)。

*为什么wait()处于Object中而不是Thread中?(有点绕 我有点懵了…)
wait()的调用必须进行加锁和释放锁操作,而锁是属于对象级别非线程级别,也就是说锁针对于对象进行操作而不是线程;而线程和锁是一对多的关系,一个线程可以拥有多把锁,而一个线程只能被一个线程拥有,为了灵活操作,就将wait()放在Object中。

LockSupport

LockSupport是对wait()的升级,无需加锁也无需释放锁;

LockSupport.park()让线程休眠,和wait()一样会让线程进入WAITING状态;

LockSupport.unpark()唤醒线程,可以唤醒对象上指定的休眠等待线程;(优势)

LockSupport与wait()区别

wait()与LockSupport的区别:

相同点:
1.二者都可以让线程进入休眠等待状态;
2.二者都可以传参或者不传参,让线程都会进入到WAITING状态。
不同点:
1.wait()需要配合加锁一起使用,LockSupport无需加锁;
2.wait()只能唤醒对象的随机休眠线程和全部线程,LockSupport可以唤醒对象的指定休眠线程。

java开发面试之如何回收线程池中多余的线程?

java开发之Java 虚拟机栈

java开发技术之Executors创建线程池的弊端

java开发之JVM基础知识分享

特别声明:以上内容(如有图片或视频亦包括在内)为自媒体平台“网易号”用户上传并发布,本平台仅提供信息存储服务。

Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.

相关推荐
热点推荐
杜锋看到了吗?他看不上的那个大个子,终于出息了,全力冲NBA

杜锋看到了吗?他看不上的那个大个子,终于出息了,全力冲NBA

萌兰聊个球
2026-05-30 09:03:28
只要1000万!皇马将回购21岁超新星:价值8000万 6月官宣

只要1000万!皇马将回购21岁超新星:价值8000万 6月官宣

叶青足球世界
2026-05-30 09:03:58
纪委再划红线!节假日公职人员这5种行为千万别碰 , 将严肃处理!

纪委再划红线!节假日公职人员这5种行为千万别碰 , 将严肃处理!

细说职场
2026-05-30 07:21:41
世界上最流行的软件,快被AI冲垮了!

世界上最流行的软件,快被AI冲垮了!

码农翻身
2026-05-29 08:59:05
广东热到离谱!几千只鸡原地中暑“躺平”,养殖户喷水抢救都没用

广东热到离谱!几千只鸡原地中暑“躺平”,养殖户喷水抢救都没用

爱下厨的阿椅
2026-05-30 01:35:07
敢说!德比斯:马西亚像神经病一样疯狂比手势 我以为我撞死人了

敢说!德比斯:马西亚像神经病一样疯狂比手势 我以为我撞死人了

念洲
2026-05-29 13:25:03
闹大了!杭州“白嫖女”被全网追杀,但说实话:她照样嫁得出去

闹大了!杭州“白嫖女”被全网追杀,但说实话:她照样嫁得出去

李昕言温度空间
2026-05-27 22:03:19
女大学生宿舍试穿抹胸裙走红,曼妙身材圈粉无数,露脸后却遭恶评

女大学生宿舍试穿抹胸裙走红,曼妙身材圈粉无数,露脸后却遭恶评

捣蛋窝
2026-05-21 06:40:07
NBA传闻:篮网队或将以1.8亿美元合同从湖人队手中抢走里夫斯

NBA传闻:篮网队或将以1.8亿美元合同从湖人队手中抢走里夫斯

好火子
2026-05-29 23:52:49
WTT挑战赛突然取消!世界乒联深夜道歉,没想到这一切都怪樊振东

WTT挑战赛突然取消!世界乒联深夜道歉,没想到这一切都怪樊振东

宝哥精彩赛事
2026-05-30 00:38:20
75岁姜昆近况:与46岁单身爱女相依为命,日子过得让人羡慕

75岁姜昆近况:与46岁单身爱女相依为命,日子过得让人羡慕

娱说瑜悦
2026-04-04 15:38:01
NBA总决赛剧本泄露?尼克斯主帅布朗幽默回应:打马刺最省钱

NBA总决赛剧本泄露?尼克斯主帅布朗幽默回应:打马刺最省钱

甜份超标的我
2026-05-30 00:57:21
欧洲女议员:购买不等于拥有 那盗版就不是偷窃

欧洲女议员:购买不等于拥有 那盗版就不是偷窃

3DM游戏
2026-05-27 22:03:20
101万亿债务压顶,全民化债时代,钱从哪里来?谁承担后果?

101万亿债务压顶,全民化债时代,钱从哪里来?谁承担后果?

牛锅巴小钒
2026-05-29 19:42:29
法网30日凌晨女单战报,中国金花创历史,一场惨案吃惊网坛

法网30日凌晨女单战报,中国金花创历史,一场惨案吃惊网坛

春日筆記
2026-05-30 04:42:24
心理学上说:如果一个人对家人不耐烦、易发火,对外人却客客气气、够温和,不是本性凉薄,根源无外乎有两点

心理学上说:如果一个人对家人不耐烦、易发火,对外人却客客气气、够温和,不是本性凉薄,根源无外乎有两点

心理观察局
2026-05-12 09:06:23
直到特朗普下令深夜突袭伊朗,全世界才明白,中国有句话说得很对

直到特朗普下令深夜突袭伊朗,全世界才明白,中国有句话说得很对

叹为观止易
2026-05-30 01:17:21
NBA重磅官宣!彻底变天了,肖华下了决心…

NBA重磅官宣!彻底变天了,肖华下了决心…

左右为篮
2026-05-30 08:05:45
老人最适合吃的高蛋白,虾肉只排第四,第一名很多人都不知道!

老人最适合吃的高蛋白,虾肉只排第四,第一名很多人都不知道!

健康科普365
2026-05-28 19:04:58
撒贝宁胡杏儿现身广东龙船,一个干划一个脚朝天,恶心一幕出现了

撒贝宁胡杏儿现身广东龙船,一个干划一个脚朝天,恶心一幕出现了

不似少年游
2026-05-29 09:32:54
2026-05-30 09:52:49
IT爱好者小尚
IT爱好者小尚
分享IT教育类信息
630文章数 55关注度
往期回顾 全部

科技要闻

英伟达、微软一同发布神秘预告 下周亮相?

头条要闻

参赛车手张秀军身亡:和领航员翻进水沟里被困一小时

头条要闻

参赛车手张秀军身亡:和领航员翻进水沟里被困一小时

体育要闻

即使是文班亚马,也做不到这件事

娱乐要闻

奚梦瑶何猷君将于6月在法国举行婚礼

财经要闻

双汇管不住一头猪

汽车要闻

900V+3.2秒破百 领克10+&领克10上市16.99万元起

态度原创

艺术
游戏
时尚
旅游
家居

艺术要闻

粉墙黛瓦别样美

《Cheap Car Repair》正式推出 好评汽修店经营

aespa治好了我的黑眼圈焦虑

旅游要闻

辽宁锦州:千年辽代国宝古建“体检养护”

家居要闻

云栖 舒展如流云

无障碍浏览 进入关怀版