重新认识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找到对应进程

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

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

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

四、特点&预防&解除

特点
  • 互斥(多个线程不能同时使用一个资源)
  • 不可剥夺(资源请求者不能强制从资源占有者手中抢夺资源,资源只能由占有者主动释放)
  • 持有并等待(当资源请求者在请求其他资源的同时保持对原有资源的占有)
  • 环路(多个线程存在环路的锁依赖关系而永远等待下去)
预防
  • 能无锁开发就无锁开发
  • 如果确实需要使用锁,核心原则:资源有序分配法(各个线程总是以相同的顺序申请自己想要的资源)
  • 合理的锁顺序
  • 更小的锁范围
  • 使用定时锁,比如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");
            }
        }
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值