龙空技术网

阿里二面:如何快速排查死锁?如何避免死锁?

老顾聊技术 4442

前言:

当前兄弟们对“死锁的本质”大体比较关注,小伙伴们都想要知道一些“死锁的本质”的相关知识。那么小编同时在网络上收集了一些对于“死锁的本质””的相关文章,希望各位老铁们能喜欢,兄弟们快快来学习一下吧!

欢迎关注头条号:老顾聊技术

精品原创技术分享,知识的组装工

前言

相信程序员都会碰上这样的问题,Java死锁如何排查?又如何解决呢?那么,何为死锁呢?死锁是指两个或两个以上的进程在执行过程中,由于竞争资源或者由于彼此通信而造成的一种阻塞的现象。今天老顾一次性来帮助大家解决Java死锁的有关问题。

实例

死锁的本质,举个例子如果此时有一个线程 A ,按照先获持有锁 a 再获取锁 b的顺序获得锁,同时另外一个线程 B,按照先获取锁 b 再获取锁 a 的顺序获取锁。如下图所示:

接着我们用代码模拟上线的执行过程

直接运行,发现主线程一直处于执行中,一直无法结束

通过jdk工具jps、jstack排查死锁问题步骤一:使用jsp查找程序进行

jps:jdk提供的一个工具,可以查看到正在运行的java进程

步骤二:使用jstack查看线程堆栈信息

jstack:jdk提供的一个工具,可以查看java进程中线程堆栈信息。更详细的用法见文档最后。

$ jstack 96521

从上面的堆栈信息中我们可以发现这个内容:“Found one Java-level deadlock”,表示程序中发现了一个死锁,后面包含跟多详细的信息,重点下面:

死锁的代码是在DeadLock.java的32行和18行,此时我们就可以去优化代码,解决死锁问题。

通过jdk提供的工具jconsole排查死锁问题

jconsole:jdk提供的一个可视化的工具,方便排查程序的一些问题,如:程序内存溢出、死锁问题等等。更详细的用法见文档最后。

jconsole位于jdk的bin目录中

$ jconsole

可以看到我们的程序,点击连接。

在jconsole窗口中查看线程堆栈信息

点击“检测死锁”,可以看到程序死锁信息

上图中可以看到详细的死锁信息,和jstack中信息类似

通过jdk提供的工具VisualVM排查死锁问题

VisualVM:jdk提供的一个非常强大的排查java程序问题的一个工具,可以监控程序的性能、查看jvm配置信息、堆快照、线程堆栈信息。算是程序优化的必备工具。

工具位于jdk的bin目录中。

$ jvisualvm

切换到“线程”窗口

执行提示有死锁情况。在线程窗口中点击“线程Dump”按钮

查看堆栈信息

线程堆栈快照的信息和jstack查看到的信息一样,即可发现死锁代码

如何避免死锁?

我们知道了死锁如何产生的,那么就知道该如何去预防。如果一个线程每次只能获取一个锁,那么就不会出现由于嵌套持有锁顺序导致的死锁。

1. 正确的顺序获得锁

如果必须获取多个锁,我们就要考虑不同线程获取锁的顺序,

上面的例子出现死锁的根本原因就是获取所的顺序是乱序的,超乎我们控制的。上面例子最理想的情况就是把业务逻辑抽离出来,把获取锁的代码放在一个公共的方法里面,让这两个线程获取锁都是从我的公共的方法里面获取。

当Thread1线程进入公共方法时,获取了A锁,另外Thread2又进来了,但是A锁已经被Thread1线程获取了,所以只能阻塞等待。Thread1接着又获取锁B,Thread2线程就不能再获取不到了锁A,更别说再去获取锁B了,这样就有一定的顺序了。只有当线程1释放了所有锁,线程B才能获取。

比如前面的例子我们改成

查看打印结果,我们发现 线程0 获取成功然后线程1才能继续获取

2. 超时放弃

当线程获取锁超时了则放弃,这样就避免了出现死锁获取的情况。当使用synchronized关键词提供的内置锁时,只要线程没有获得锁,那么就会永远等待下去,然而Lock接口提供了boolean tryLock(long time, TimeUnit unit) throws InterruptedException方法,该方法可以按照固定时长等待锁,因此线程可以在获取锁超时以后,主动释放之前已经获得的所有的锁。通过这种方式,也可以很有效地避免死锁。

总结

死锁就是“两个任务以不合理的顺序互相争夺资源”造成,因此为了规避死锁,应用程序需要妥善处理资源获取的顺序。 另外有些时候,死锁并不会马上在应用程序中体现出来,在通常情况下,都是应用在生产环境运行了一段时间后,才开始慢慢显现出来,在实际测试过程中,由于死锁的隐蔽性,很难在测试过程中及时发现死锁的存在,而且在生产环境中,应用出现了死锁,往往都是在应用状况最糟糕的时候——在高负载情况下。因此,开发者在开发过程中要谨慎分析每个系统资源的使用情况,合理规避死锁。

---End---

老顾的微服务网关分享课程,请大家多多支持

推荐阅读

a、dubbo如何处理业务异常,这个一定要知道哦!

b、企业级SpringBoot应用多个子项目配置文件规划、多环境支持(一)

c、企业级SpringBoot应用多个子项目配置文件规划、多环境支持(二)

d、企业级SpringBoot应用多个子项目配置文件之配置中心(三)

e、利用阿里开源工具进行排查线上CPU居高问题

1、基于RocketMq的SpringCloud Stream框架实战入门

2、如何搭建消息中间件应用框架之SpringCloud Stream

3、面试必备:网关异常了怎么办?如何做全局异常处理?

4、Gateway网关系列(二):SpringCloud Gateway入门实战,路由规则

5、Gateway网关系列开篇:SpringCloud的官方网关Gateway介绍

6、API网关在微服务架构中的应用,这一篇就够了

7、学习Lambda表达式看这篇就够了,不会让你失望的哦(续篇)

8、Lambda用在哪里?几种场景?

9、为什么会出现Lambda表达式,你知道吗?

10、不说“分布式事务”理论,直接上大厂阿里的解决方案,绝对实用

11、女程序员问到这个问题,让我思考了半天,Mysql的“三高”架构

12、大厂二面:CAP原则为什么只能满足其中两项?而不能同时满足

13、阿里P7二面:聊聊零拷贝的原理

14、秒杀系统的核心点都在这里,快来取

15、你了解如何利用token方式实现分布式Session吗?

16、Mysql索引结构演变,为什么最终会是那个结构呢?让你一看就懂

17、一场比赛涉及到的知识,用通俗易通的方式介绍并发协调

18、企业实战Redis全方面思考,你思考了吗?

19、面试题:Thread的start和run的区别

20、面试题:什么是CAS?CAS的作用以及缺点

21、如何访问redis中的海量数据?避免事故产生

22、如何解决Redis热点问题?以及如何发现热点?

23、如何设计API接口,实现统一格式返回?

24、你真的知道在生产环境下如何部署tomcat吗?

25、分享一线互联网大厂分布式唯一ID设计 之 snowflake方案

26、分享大厂分布式唯一ID设计方案,快来围观

27、你想了解一线大厂的分布式唯一ID生成方案吗?

28、你知道如何处理大数据量吗?(数据拆分篇)

29、如何永不迁移数据和避免热点? 根据服务器指标分配数据量(揭秘篇)

30、你知道怎么分库分表吗?如何做到永不迁移数据和避免热点吗?

31、你了解大型网站的页面静态化吗?

32、你知道如何更新缓存吗?如何保证缓存和数据库双写一致性?

33、你知道怎么解决DB读写分离,导致数据不一致问题吗?

34、DB读写分离情况下,如何解决缓存和数据库不一致性问题?

35、你真的知道怎么使用缓存吗?

36、如何利用锁,防止缓存击穿?重构思想的重要性

37、海量订单产生的业务高峰期,如何避免消息的重复消费?

38、你知道如何保障生产端100%消息投递成功吗?

39、微服务下的分布式session该如何管理?

40、阿里二面:filter、interceptor、aspect应如何选择?很多人中招

41、互联网架构重要组员CDN,很多高级开发都没有实操过,来看这里

42、阿里二面:CDN缓存控制原理,看看能不能难住你

43、SpringCloud Alibaba之Nacos多环境多项目管理

44、SpringCloud Alibaba系列之Nacos配置中心玩法

45、SpringCloud Alibaba之Nacos注册中心

46、SpringCloud Plus版本之SpringCloud Alibaba

47、SpringCloud Alibaba之Nacos集群、持久化

48、SpringCloud Alibaba之Nacos共享配置、灰度配置

49、SpringCloud Alibaba之Sentinel工作原理

50、SpringCloud Alibaba之Sentinel流控管理

51、SpringCloud Alibaba之Sentinel降级管理

52、SpringCloud Alibaba之Sentinel热点参数限流

53、SpringCloud Alibaba之Sentinel的API实战

标签: #死锁的本质