首先看一个必然死锁的例子
package com.study.deadlock;
public class MustDeakLock implements Runnable {
int flag = 1;
static Object o1 = new Object();
static Object o2 = new Object();
public static void main(String[] args) {
MustDeakLock m1 = new MustDeakLock();
MustDeakLock m2 = new MustDeakLock();
m1.flag = 1;
m2.flag = 0;
Thread thread1 = new Thread(m1);
Thread thread2 = new Thread(m2);
thread1.start();
thread2.start();
}
@Override
public void run() {
if(flag == 1){
synchronized (o1){
try {
Thread.sleep(800);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("我得到锁1");
synchronized (o2){
System.out.println("我得到锁2");
}
}
}
if(flag == 0){
synchronized (o2){
try {
Thread.sleep(800);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("我得到锁2");
synchronized (o1){
System.out.println("我得到锁1");
}
}
}
}
}
死锁的四个条件
互斥条件:相同的锁不能被线程同时持有
请求与保持:保持自己的锁请求别人的锁
不剥夺条件:没有外力可以调解
循环等待:多个线程互相循环等待
定位死锁
- jps jstack
- ThreadMXBean
ThreadMXBean threadMXBean = ManagementFactory.getThreadMXBean(); long[] deadlockedThreads = threadMXBean.findDeadlockedThreads(); for(int i = 0; i<deadlockedThreads.length; i++){ ThreadInfo threadInfo = threadMXBean.getThreadInfo(deadlockedThreads[i]); System.out.println(threadInfo.getThreadName()); }
避免死锁策略
- 设置超时时间
- 获取锁的顺序
- 多使用并发类
- 降低锁的粒度