集团主站
欢迎来到成都达内官方网站!达内—美国上市公司 亿元级外企IT培训企业!
成都it培训哪家好
成都it培训哪家好
全国服务监督电话:15023458194  |   联系客服   |
当前位置:主页 > 培训课程 > Java >

成都java工程师讲讲Java中的死锁问题

发布者: 成都达内     浏览次数:     发布时间:2019-05-09 10:34:27

今天成都java工程师来讲讲java中的死锁问题,大致分为下面三个小点:如何检测死锁、如何预防死锁、隐蔽的死锁...

  成都java工程师讲讲Java中的死锁问题

  今天我们来讲讲java中的死锁问题,大致分为下面三个小点

  如何检测死锁

  如何预防死锁

  隐蔽的死锁

  正文

  如何检测死锁首先,我们先明白在什么情况下会怀疑是死锁?

  简单,就是程序没有响应的时候。其实排查步骤和《谈谈线上CPU100%排查套路》是类似的。但是有一个区别,在死锁的情况下,cpu不会跑满。

  也就是说,当你发现程序没有响应,cpu占用率又不是特别高的时候,第一反应就是应该是死锁。

  那么,死锁发生的情形也很简单,如下图所示,

  成都java工程师讲讲Java中的死锁问题

  我们准备一段程序,模拟一下

  成都java工程师讲讲Java中的死锁问题

  排查步骤也很简单,执行下面的jps命令看看当前执行任务的进程号

  D:Java>jps22320 Launcher2748825612 Jps6700 TestDeadLock

  然后用jstack命令打印出6700这个进程中,线程的信息

  D:Java>jstack 6700

  输出结果中,有这么一段,就能看到死锁线程信息

  成都java工程师讲讲Java中的死锁问题

  多嘴一句,在输出结果中你能看到线程的各种状态,如下所示

  成都java工程师讲讲Java中的死锁问题

  Thread的源码中有一个State枚举类定义了这些线程状态,转换关系如下(图片出自网络)

  成都java工程师讲讲Java中的死锁问题

  初始状态

  实现Runnable接口和继承Thread可以得到一个线程类,new一个实例出来,线程就进入了初始状态。

  就绪状态

  就绪状态只是说你资格运行,调度程序没有挑选到你,你就永远是就绪状态。

  调用线程的start()方法,此线程进入就绪状态。

  当前线程sleep()方法结束,其他线程join()结束,等待用户输入完毕,某个线程拿到对象锁,这些线程也将进入就绪状态。

  当前线程时间片用完了,调用当前线程的yield()方法,当前线程进入就绪状态。

  锁池里的线程拿到对象锁后,进入就绪状态。

  运行中状态

  线程调度程序从可运行池中选择一个线程作为当前线程时线程所处的状态。这也是线程进入运行状态的唯一一种方式。

  阻塞状态

  阻塞状态是线程阻塞在进入synchronized关键字修饰的方法或代码块(获取锁)时的状态。

  等待

  处于这种状态的线程不会被分配CPU执行时间,它们要等待被显式地唤醒,否则会处于无限期等待的状态。

  超时等待

  处于这种状态的线程不会被分配CPU执行时间,不过无须无限期等待被其他线程显示地唤醒,在达到一定时间后它们会自动唤醒。

  终止状态

  当线程的run()方法完成时,或者主线程的main()方法完成时,我们就认为它终止了。这个线程对象也许是活的,但是,它已经不是一个单独执行的线程。线程一旦终止了,就不能复生。

  在一个终止的线程上调用start()方法,会抛出java.lang.IllegalThreadStateException异常。

  如何预防死锁尽量保证加锁顺序是一样的

  例如有A,B,C三把锁。

  Thread 1的加锁顺序为A、B、C这样的。

  Thread 2的加锁顺序为A、C

  这样就不会死锁。

  如果Thread2的加锁顺序为B、A或者C、A这样顺序就不一致了,就会出现死锁问题。

  尽量用超时放弃机制

  Lock接口提供了tryLock(long time, TimeUnit unit)方法,该方法可以按照固定时长等待锁,因此线程可以在获取锁超时以后,主动释放之前已经获得的所有的锁。可以避免死锁问题

  隐蔽的死锁因为我在生产上碰到过几次死锁,线程日志里是看不到死锁信息的。一般这种情况下都是直接看线程栈的内容,自己分析。

  例如下面这个并发加载类导致的死锁

  成都java工程师讲讲Java中的死锁问题

  成都java工程师讲讲Java中的死锁问题

  成都java工程师讲讲Java中的死锁问题

  代码很简单,准备两个线程并行加载,在A类中加载B类。而在B类中加载A类。就会导致死锁,此时按上述步骤是看不到死锁信息的。你只能看到下面这样的信息

  成都java工程师讲讲Java中的死锁问题

  线程都是处在Runable状态的,看不到死锁信息。

  原因也很简单:

  static代码里头的内容会被编译放到clinit方法里。JVM执行clinit时会给clinit加上锁,防止多线程并发执行。两个线程在初始化的时候,先各自加上clinit锁。然后在通过Class.forName去加载对方,因此都想获取对方要执行clinit的锁,因此死锁就此发生。

  总结

  本文讲了java中死锁相关知识,希望大家有所收获!

(责任编辑:范老师)
最新开班
  • 成都Java培训班
    免费试听名额发放中...
  • 成都C++培训班
    免费试听名额发放中...
  • 成都PHP培训班
    免费试听名额发放中...
  • 成都网络工程培训班
    免费试听名额发放中...
  • 成都Unity3D培训班
    免费试听名额发放中...
  • 成都大数据培训班
    免费试听名额发放中...
  • 成都uid培训班
    免费试听名额发放中...
  • 成都会计培训班
    免费试听名额发放中...
  • 成都Python培训班
    免费试听名额发放中...
  • 成都嵌入式培训班
    免费试听名额发放中...
  • 成都web培训班
    免费试听名额发放中...
  • 成都软件测试培训班
    免费试听名额发放中...
在线留言
提交

校区地址:绵阳市涪城区临园路东段68号富临大都会7栋3单元9层12号

联系电话:15023458194

公交路线:富乐路口凯德广场(10路;29路;3路;15路;11路;15a路;71路)

校区地址:成都市锦江区东大街紫东楼端35号明宇金融广场19楼1906室

联系电话:15023458194

公交路线:芷泉街(18路;21路;43路;48路;104路;152路;335路 ) 地铁路线:东门大桥站(地铁2号线)

校区地址:成都市高新区奥克斯广场蜀锦路209号一楼商铺

联系电话:15023458194

公交路线:益州大道锦城大道口(18路;21路;43路;48路;104路;152路;335路 ) 地铁路线:孵化园(地铁1号线)

校区地址:成都锦江区东大街芷泉街229号东方广场C座3楼303

联系电话:15023458194

公交路线:芷泉街(188路;115路;515路;236路;505路;501路;84路 ) 地铁路线:东门大桥站(地铁2号线)

校区地址:成都市武侯区佳灵路3号红牌楼广场2号写字楼11楼1115号

联系电话:15023458194

公交路线:红牌楼东(11路;92路;100路;111路;139路;g28路;快速公交K1/K2) 地铁路线:红牌楼站(地铁3号线)

校区地址:成都市锦江区红星路二段70号四川日报大厦502-2

联系电话:15023458194

公交路线:市二医院站(6路;49路;102路;5路;37路;g92路;) 地铁路线:地铁市二医院(地铁3号线)

校区地址:成都市锦江区东大街芷泉段229号东方广场C座16层

联系电话:15023458194

公交路线:芷泉街(18路;21路;43路;48路;104路;152路;335路 ) 地铁路线:东门大桥站(地铁2号线)

校区地址:四川省成都市武侯区高新科技孵化园9号园区E座7楼

联系电话:15023458194

公交路线:益州大道锦城大道口(18路;21路;43路;48路;104路;152路;335路 ) 地铁路线:孵化园(地铁1号线)

校区地址:成都市人民南路一段86号“城市之心”大厦26楼

联系电话:15023458194

公交路线:成都市人民南路(6路;14路;42路;72路;76路;1010路;)

校区地址:成都市高新区奥克斯广场B座1708

联系电话:15023458194

公交路线:益州大道锦城大道口(18路;21路;43路;48路;104路;152路;335路 ) 地铁路线:孵化园(地铁1号线)

了解达内动态
关注成都达内教育公众号

首页 | 关于达内 | 课程中心 | 专家师资 | 视频教程 | 学员空间 | 校企合作 | 新闻资讯 | 就业指导 | 网站地图

2016-2025 达内时代科技集团有限公司 版权所有 京ICP证8000853号-56