重新认识Java中的死锁问题

一、定义

多个进程因抢夺系统资源而产生相互等待的现象。

二、场景模拟

package com.gui.practise.thread.deadlock;

public class DeadLock {
    private final Object resource1 = new Object();//资源 1    
    private final Object resource2 = new Object();//资源 2    
    public void leftRight() {
        synchronized (resource1) {
            System.out.println(Thread.currentThread() + "get resource1");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            System.out.println(Thread.currentThread() + "waiting get resource2");

            synchronized (resource2) {
                System.out.println(Thread.currentThread() + "get resource2");
            }
        }
    }

    public void rightLeft() {
        synchronized (resource2) {
            System.out.println(Thread.currentThread() + "get resource2");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            System.out.println(Thread.currentThread() + "waiting get resource1");

            synchronized (resource1) {
                System.out.println(Thread.currentThread() + "get resource1");
            }
        }
    }
}
package com.gui.practise.thread.deadlock;

public class DeadLockTest {
    public static void main(String[] args) {
        DeadLock dl = new DeadLock();
        new Thread(() -> {
            dl.leftRight();
        }, "线程 1").start();

        new Thread(() -> {
            dl.rightLeft();
        }, "线程 2").start();
    }
}

三、死锁检测

Java自带工具检测死锁

第一步:jps找到对应进程

重新认识Java中的死锁问题_第1张图片

第二步:jstack查看对应堆栈信息

重新认识Java中的死锁问题_第2张图片

重新认识Java中的死锁问题_第3张图片

阿里巴巴开源的java诊断工具arthas

下载地址:https://github.com/alibaba/arthas/releases

重新认识Java中的死锁问题_第4张图片

重新认识Java中的死锁问题_第5张图片

四、特点&预防&解除

特点
  • 互斥(多个线程不能同时使用一个资源)
  • 不可剥夺(资源请求者不能强制从资源占有者手中抢夺资源,资源只能由占有者主动释放)
  • 持有并等待(当资源请求者在请求其他资源的同时保持对原有资源的占有)
  • 环路(多个线程存在环路的锁依赖关系而永远等待下去)
预防
  • 能无锁开发就无锁开发
  • 如果确实需要使用锁,核心原则:资源有序分配法(各个线程总是以相同的顺序申请自己想要的资源)
  • 合理的锁顺序
  • 更小的锁范围
  • 使用定时锁,比如Lock类中的tryLock方法
解除
  • 直接重启服务,如果代码未进行修复,问题还会出现
  • 使用定时锁方案,Lock的tryLock方法

五、使用资源有序分配法解除场景模拟中的死锁问题

package com.gui.practise.thread.deadlock;

public class DeadLock {
    private final Object resource1 = new Object();//资源 1    
    private final Object resource2 = new Object();//资源 2    
    public void leftRight() {
        synchronized (resource1) {
            System.out.println(Thread.currentThread() + "get resource1");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            System.out.println(Thread.currentThread() + "waiting get resource2");

            synchronized (resource2) {
                System.out.println(Thread.currentThread() + "get resource2");
            }
        }
    }

    public void rightLeft() {
        synchronized (resource1) {
            System.out.println(Thread.currentThread() + "get resource1");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            System.out.println(Thread.currentThread() + "waiting get resource2");

            synchronized (resource2) {
                System.out.println(Thread.currentThread() + "get resource2");
            }
        }
    }
}

你可能感兴趣的:(Java,Java,死锁,死锁检测,Java死锁)