- 什么是死锁
- 死锁检测
- 产生死锁的四个必要条件
- 如何避免死锁
死锁
死锁,指两个或多个线程之间,由于互相持有对方需要的锁,而永久处于阻塞的状态。
死锁
- 死锁示例代码
public class DeadLockSimple extends Thread {
private String first;
private String second;
public DeadLockSimple(String name, String first, String second) {
super(name);
this.first = first;
this.second = second;
}
@Override
public void run() {
super.run();
synchronized (first) {
System.out.println(this.getName() + ",obtained1:" + first);
try {
Thread.sleep(1000L);
synchronized (second) {
System.out.println(this.getName() + ",obtained2:" + second);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
//死锁检测
ThreadMXBean mxBean = ManagementFactory.getThreadMXBean();
Runnable dlCheck = new Runnable() {
@Override
public void run() {
long[] threadIds = mxBean.findDeadlockedThreads();
if (threadIds != null) {
ThreadInfo[] threadInfos = mxBean.getThreadInfo(threadIds);
System.out.println("Detected deadlock threads:");
for (ThreadInfo threadInfo : threadInfos) {
System.out.println(threadInfo.getThreadName());
}
}
}
};
ScheduledExecutorService scheduledExecutorService= Executors.newScheduledThreadPool(1);
scheduledExecutorService.scheduleAtFixedRate(dlCheck,5L,10L, TimeUnit.SECONDS);
//死锁示例
String lockA = "lockA";
String lockB = "lockB";
DeadLockSimple t1 = new DeadLockSimple("thread1", lockA, lockB);
DeadLockSimple t2 = new DeadLockSimple("thread2", lockB, lockA);
t1.start();
t2.start();
try {
t1.join();
t2.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
输出
thread2,obtained1:lockB
thread1,obtained1:lockA
Detected deadlock threads:
thread2
thread1
死锁检测:通过相关工具检测死锁。
- Jstack命令
- JConsole工具
产生死锁的四个必要条件
- 互斥条件:一个资源每次只能被一个进程使用。
- 占有且等待:一个进程因请求资源而阻塞时,对已获得的资源保持不放。
- 没有强行占有:进程已获得的资源,在末使用完之前,不能强行剥夺。
- 循环等待条件:若干进程之间形成一种头尾相接的循环等待资源关系。
如何避免死锁
-
加锁顺序:确保所有的线程都是按照相同的顺序获得锁,那么死锁就不会发生
image.png -
加锁时限:尝试获取锁的时候加一个超时时间,这也就意味着在尝试获取锁的过程中若超过了这个时限该线程则放弃对该锁请求
image.png
网友评论