死锁是一种特定的状态,由于循环依赖导致彼此处于等待,所以出现死锁的情况,简单总结如下
就是两者都持有对方需要的资源,并且不放手
死锁的常见定位就是利用jstack等工具,定位互相依赖的关系,然后找到死锁,JConsole可以再图形界面进行有限的死锁检测
我们这次就对于检测死锁的方式进行讲解
我们先看一个明显的死锁场景
public class DeadLockSample extends Thread {
private String first; private String second; public DeadLockSample(String name, String first, String second) { super(name); this.first = first; this.second = second; } public void run() { synchronized (first) { System.out.println(this.getName() + ” obtained: ” + first); try { Thread.sleep(1000L); synchronized (second) { System.out.println(this.getName() + ” obtained: ” + second); } } catch (InterruptedException e) { // Do nothing } } } public static void main(String[] args) throws InterruptedException { String lockA = “lockA”; String lockB = “lockB”; DeadLockSample t1 = new DeadLockSample(“Thread1”, lockA, lockB); DeadLockSample t2 = new DeadLockSample(“Thread2”, lockB, lockA); t1.start(); t2.start(); t1.join(); t2.join(); } } |
我们可以利用其看一下死锁的出现,对于死锁的检测,可以看jstack命令,或者利用JConsole图形化工具
分析得到的输出,可以看如下
我们看出来上面每一个线程,都是持有了对方等待的锁
那么,其实总结是否是死锁了,就是利用查看线程的状态,对比Monitor的持有状态
而且Java内部也提供了管理API,ThreadMXBean,可以利用其对应的api去定位,去查找
代码可以如下
public static void main(String[] args) throws InterruptedException {
ThreadMXBean mbean = ManagementFactory.getThreadMXBean(); Runnable dlCheck = new Runnable() { @Override public void run() { long[] threadIds = mbean.findDeadlockedThreads(); if (threadIds != null) { ThreadInfo[] threadInfos = mbean.getThreadInfo(threadIds); System.out.println(“Detected deadlock threads:”); for (ThreadInfo threadInfo : threadInfos) { System.out.println(threadInfo.getThreadName()); } } } }; ScheduledExecutorService scheduler =Executors.newScheduledThreadPool(1); // 稍等5秒,然后每10秒进行一次死锁扫描 scheduler.scheduleAtFixedRate(dlCheck, 5L, 10L, TimeUnit.SECONDS); // 死锁样例代码… } |
这样的代码,会输出对应的死锁的输出,可以收集对应的数据,但是还是一个相对重量级的操作
那么,如何去预防对应的死锁呢?
避免 互斥
互斥也要立即释放
避免循环依赖
那么第一种方法就是尽可能的避免使用多个锁,在Java NIO中,本身模型中具有多个锁,所以可能导致死锁
第二个模式,设计好对应的锁的获取顺序,可以参考最近的银行家算法
从而避免死锁
第三种,就是带有超时的获取锁
利用所谓的timed_waited 去尝试获取锁,没有获取到就直接进行退出
第四种,就是去分析死锁的可能出现场景
在类加载阶段,是可能出现死锁的,jstack等工具也不能显示全部锁信息,所以比较棘手