出自:https://www.jianshu.com/p/68c0fef7b63e
一、死锁讲解
在Java中使用多线程,就会有可能导致死锁问题。死锁会让程序一直卡住,不再程序往下执行。我们只能通过中止并重启的方式来让程序重新执行。(只要发生了死锁,只能中止并重启服务,tryLock也是解决了死锁)
这是我们非常不愿意看到的一种现象,我们要尽可能避免死锁的情况发生!
造成死锁的原因可以概括成三句话:
当前线程拥有其他线程需要的资源
当前线程等待其他线程已拥有的资源
都不放弃自己拥有的资源
二、 避免死锁的方法
避免死锁可以概括成三种方法:
固定加锁的顺序(针对锁顺序死锁)
开放调用(针对对象之间协作造成的死锁),不在方法上加锁,而是用同步代码块
使用定时锁-->tryLock()
总结
发生死锁的原因主要由于:
1、线程之间交错执行
解决:以固定的顺序加锁
2、执行某方法时就需要持有锁,且不释放
解决:缩减同步代码块范围,最好仅操作共享变量时才加锁
开放方法的调用(尽量不在方法上加锁,而是使用同步代码块)
3、永久等待
解决:使用tryLock()定时锁,超过时限则返回错误信息。tryLock方法可以设置参数,等待获得超时就抛出异常,记得根据具体业务处理这个异常。(这种方式大概不推荐)
三、举例:
上面是脱离具体业务的例子
1、银行业务(锁顺序死锁)
解决:
2、某个业务(对象之间协作造成的死锁)
解决:如下,获得c的锁之前,已经释放掉了b的锁,
四、死锁检测
虽然造成死锁的原因是因为我们设计得不够好,但是可能写代码的时候不知道哪里发生了死锁。
JDK提供了两种方式来给我们检测:
JconsoleJDK自带的图形化界面工具,使用JDK给我们的的工具JConsole(jdk目录,bin目录下,和jvisualvm在同一个目录下)
Jstack是JDK自带的命令行工具,主要用于线程Dump分析。