每日一面——谈谈你对死锁的认识

菜鸡每日一面系列打卡20

每天一道面试题目 

助力小伙伴轻松拿offer

坚持就是胜利,我们一起努力!

题目描述

谈谈你对死锁的认识。

题目分析

前几篇文章主要讲述了线程安全的三种解决方式:互斥同步非阻塞同步无同步方案。而本文主要讲的是互斥同步方案的一个衍生问题,死锁。不了解互斥同步的小伙伴,可以移步文末的相关链接进行学习。

互斥同步,通俗地说,就是采用加锁的方式来保证同步,但如果处理不当,可能会引发死锁,这是实际工作中可能会遇到的问题,相较于纯理论的考查,面试官更倾向于理论与实践相结合,因此,正确理解死锁的相关概念及解决方式是很有必要的。

接下来,随菜鸡一起去看看吧。

题目解答

01

什么是死锁

当一个线程永远地持有一个锁,并且其他线程都尝试获得这个锁时,那么它们将永远被阻塞。在线程A持有锁Lock1并想获得锁Lock2的同时,线程B持有锁Lock2并尝试获得锁Lock1,那么这两个线程将永远地等待下去。这种情况就是最简单的死锁形式,其中多个线程由于存在环路的锁依赖关系而永远地等待下去。

常见的死锁大致分为两种:锁顺序死锁资源死锁

  • 锁顺序死锁:顾名思义,因为获取锁的顺序不同而导致的死锁。举个例子:

每日一面——谈谈你对死锁的认识_第1张图片

此时,线程A与B获取锁的顺序不会引发死锁。

每日一面——谈谈你对死锁的认识_第2张图片

而此时,线程A与B获取锁的顺序则引发了死锁。

上述现象说明了一个问题,死锁问题不一定是必现的,因此,会给发现死锁问题的排查与诊断带来一定的困难,需要格外注意。

  • 资源死锁:当多个线程在相同的资源集合上等待时,会发生死锁。出现情况与锁顺序死锁类似,只是由锁的获取转换为资源的获取。在此不再赘述。

02

如何避免死锁

针对死锁出现的原因,我们可以有针对性地进行避免。

以锁顺序死锁为例,如果一个程序每次至多只能获得一个锁,那么就不会产生锁顺序死锁。因此,在程序中需要尽可能地避免获取多个锁的情况,如果必须获取多个锁,那么在设计时必须考虑锁的顺序。

另外,如果程序必须获取多个锁,可以考虑采用Lock接口的实现类中的定时tryLock功能来代替内置锁机制。这样就可以在长时间获取不到锁时,避免进入永久等待的尴尬境地。

03

如何诊断死锁

死锁问题的诊断可以采用以下思路:工具探测线程转储信息分析代码排查

  • 工具探测:首先,使用诸如Jconsole之类是工具进行检测,判断是否真正发生了死锁。

  • 线程转储信息分析:如果工具检测确实发生了死锁,接下来可以采用相应的命令来查询JVM的线程转储信息,根据信息定位哪些锁导致了这个问题,涉及了哪些线程,它们持有哪些其他的锁,以及是否间接地给其他线程带来不利影响。

  • 代码排查:最后,根据线程转储信息的分析结果,定位涉及代码的范围,并以出现死锁的原因为根本依据进行排查与修复。

以上便是菜鸡对死锁问题的一些总结,供大家参考。

参考资料

《Java并发编程实战》Brian Goetz等著

相关链接

每日一面——谈谈你对synchronized关键字的理解

每日一面——谈谈你对ReentrantLock的理解

学习 | 工作 | 分享

????长按关注“有理想的菜鸡

只有你想不到,没有你学不到

你可能感兴趣的:(面试经验)