java死锁介绍、源码实现及预防(含源码)

java死锁介绍、源码实现及预防(含源码)

什么是死锁

死锁是 多个线程 之间 相互之间 持有 对方需要的资源同时 又等待获取 对方持有资源的 一种尴尬状态;

比如:两个铁匠张铁匠和李铁匠, 都在打造 一把 武器,他们 都要使用 炉子和铁锤,但是这时候只有一个炉子和一个铁锤(只能同时满足一个人使用),在某一个时刻,张铁匠在使用 炉子 而 李铁匠 在使用铁锤 两个人都在等待 对方的工具使用完,进行下一个工序,(两个人都有一个特性:对方不闲下来 我就一直占着 这个工具),这样就造成了,两个人都不能完成下个工序,一直等待

死锁的条件

1、互斥使用,即当资源被一个线程使用(占有)时,别的线程不能使用
2、不可抢占,资源请求者不能强制从资源占有者手中夺取资源,资源只能由资源占有者主动释放。
3、请求和保持,即当资源请求者在请求其他的资源的同时保持对原有资源的占有。
4、循环等待,即存在一个等待队列:P1占有P2的资源,P2占有P3的资源,P3占有P1的资源。这样就形成了一个等待环路。

代码实现

public class DeadLock {

    public static void main(String[] args) {
        DeadLockTest();

    }

    public static void DeadLockTest() {
        // 创建两把 对象锁
        Object o = new Object();

        Object o1 = new Object();

        // 此线程 首先 拿锁1 然后 拿锁2
        new Thread(() -> {
            worker(o, o1);
        }, "worker1").start();

        // 此线程 首先 拿锁2 然后 拿锁1
        new Thread(() -> {
            worker(o1, o);
        }, "worker2").start();
    }

    /**
     * 一个worker 完成一个 工作需要 获取两把锁
     *
     * @param lock0 锁1
     * @param lock1 锁2
     */
    public static void worker(Object lock0, Object lock1) {
        synchronized (lock0) {
            System.out.println("get com.studynote.lock:" + lock0.toString() + "============" + Thread.currentThread().getName() + " is running");
            synchronized (lock1) {
                System.out.println("get com.studynote.lock:" + lock1.toString() + "============" + Thread.currentThread().getName() + " is running");
            }
        }
    }


}

如何预防死锁

给锁加过期时间

指定加锁顺序

使用算法

有序资源分配法

银行家算法

死锁检测

死锁检测是一个更好的死锁预防机制,它主要是针对那些不可能实现按序加锁并且锁超时也不可行的场景。

每当一个线程获得了锁,会在线程和锁相关的数据结构中(map、graph等等)将其记下。除此之外,每当有线程请求锁,也需要记录在这个数据结构中。

猜你喜欢

转载自blog.csdn.net/qq_41692766/article/details/105922992