1 死锁的产生条件
- 资源互斥,每个资源一次只能被一个线程持有
- 资源不可抢夺
- 占用并等待资源,涉及的线程当前至少持有一个资源并申请其他资源,而这些资源恰好被其他线程持有
- 循环等待资源
2 死锁的排查
Jstack、arthas、jvisualvm 直接检查
3 如何解决
3.1 已经产生
重启
3.2 修复
从占用并等待资源和循环等待资源角度考虑
- 锁粗法
用一个粗粒度的锁代替原来多个细粒度的锁,这样每个线程只申请一个锁,避免了死锁。
但是这个方法会导致资源浪费。避免了“循环等待资源”的必要条件。 - 锁排序法
相关线程使用全局统一的顺序申请锁,消除“循环等待资源”的必要条件,比如一个对象方法要申请两个锁,先申请hashcode值小的那个锁,然后再申请hashcode值大的那个锁。如果存在两个锁的hashcode相同,可以退化成粗锁法。
“循环等待资源”实际为每个对象使用局部顺序去申请锁,如果依赖全局统一的顺序,即可消除“循环等待资源”的必要条件。 - ReentrantLock.tryLock(long, TimeUnit),为申请锁这个操作指定一个超时时间
避免了“占用并等待资源”的必要条件。 - 开放调用
一个方法在调用外部方法时不持有任何锁。避免了“占用并等待资源”的必要条件。 - 不用锁