立即学习:https://edu.csdn.net/course/play/26270/326861?utm_source=blogtoedu
1、避免死锁
- 不使用锁,不使用2把及以上的锁
- 必须使用2把及以上锁的时候,确保在整个应用程序中对获取锁的顺序是一致的
- 尝试获取具有超时释放的锁时,例如Locak中的tryLock来获取锁
- 当发生了java-level锁时,重启程序来干掉进程/线程
package test; public class DemoLocak { private static final Object lock1 = new Object(); private static final Object lock2 = new Object(); public static void main(String[] args) { newThread("ThreadA", lock1, lock2).start(); newThread("ThreadB", lock2, lock1).start(); //改成以下情况不会造成死锁,满足第2种情况 //newThread("ThreadB", lock1, lock2).start(); } private static Thread newThread(String threadName, Object lockFrist, Object lockSecond) { return new Thread(() -> { synchronized (lockFrist) { System.out.println(Thread.currentThread().getName() + " holiding lockFrist!"); System.out.println(threadName + " holiding!"); try { Thread.sleep(300L); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } System.out.println(threadName + " waitting lockFrist!"); synchronized (lockSecond) { System.out.println(threadName + " holiding lockSecond!"); } } }, threadName); } }
2、定位死锁问题
-
jps 例举正在运行的虚拟机进程并显示虚拟机执行的主类以及这些进程的唯一ID(PID)
- jstack 用于JVN当前时刻的线程快走,得到JVM当前每一条线程正在执行的堆栈信息,定位线程长时间卡顿问题,如死锁、死循环等问题
- 运行程序,在terminal输入jps查看目前所有的线程,查看目前是否有阻塞的线程。第二,输入 jstack 进程id,查看当前进程详情的堆栈信息 jstack 进程id(阻塞进程id)
3、处理数据库的死锁问题
死锁情景:
- 针对同一张表
- 开启2个会话,每个会话调用 start tran
- 第一个会话先更新id=1的行
- 第二个会话先更新id=2的行
- 第一个会话先更新id=2的行,此时等待id=2行的锁
- 第二个会话更新id=1的行,此时数据库检测死锁,种植触发死锁的事务,第一个会话的等待状态变为正常状态
- 调用“commit”提交第一个会话事务,数据成功