死锁产生原因:
- 当前线程拥有其他线程需要的资源
- 当前线程等待其他线程已拥有的资源
- 都不放弃自己拥有的资源
public class LeftRightDeadlock { private final Object left = new Object(); private final Object right = new Object(); public void leftRight() { // 得到left锁 synchronized (left) { // 得到right锁 synchronized (right) { doSomething(); } } } public void rightLeft() { // 得到right锁 synchronized (right) { // 得到left锁 synchronized (left) { doSomethingElse(); } } } }
线程A调用leftRight()
方法,得到left锁,同时线程B调用rightLeft()
方法,得到right锁;线程A和线程B都继续执行,此时线程A需要right锁才能继续往下执行。
此时线程B需要left锁才能继续往下执行。但是:线程A的left锁并没有释放,线程B的right锁也没有释放。所以他们都只能等待,而这种等待是无期限的-->永久等待-->死锁。
产生死锁的必要条件:
互斥条件、请求和保持条件、不可抢占条件、循环等待条件
处理死锁的思路:
- 预防死锁:破坏死锁的四个必要条件中的一个或多个。(破坏请求和保持条件、破坏不可抢占条件、破坏循环等待条件)
- 避免死锁:在资源动态分配过程中,用某种方式防止系统进入不安全的状态。
- 检测死锁:是否出现环。
- 解除死锁:通常撤销进程,回收资源,再分配给正处于阻塞状态的进程。
从Java层面预防死锁:
- 线程之间交错执行-》以固定的顺序加锁。
- 执行某方法时就需要持有锁,且不释放-》缩减同步代码块范围,最好仅操作共享变量时才加锁。
- 永久等待-》使用
tryLock()
定时锁,超过时限则返回错误信息.