死锁相关知识整理

死锁的产生

死锁概念:并发下,线程因为相互等待对方资源,导致"永久"阻塞的现象。

死锁产生的4大必要条件

  1. 资源互斥:一个资源每次只能被一个线程使用
  2. 请求与保持条件:一个线程因请求资源而阻塞时,对方已经获得的资源保持不变
  3. 不剥夺条件:线程已经获得的资源,在未使用之前不能剥夺
  4. 循环等待条件:若干线程形成的一种首尾相接的循环等待资源关系

死锁示例

package com.DeadLock;

/**
 * @author wty
 * @date 2022/10/17 15:36
 * <p>
 * 模拟死锁过程
 */
public class DeadLock {
    public static void main(String[] args) {
        DeadLockExercise deadLockExercise1 = new DeadLockExercise(true);
        deadLockExercise1.setName("A线程");
        DeadLockExercise deadLockExercise2 = new DeadLockExercise(false);
        deadLockExercise2.setName("B线程");

        deadLockExercise1.start();
        deadLockExercise2.start();
    }
}

class DeadLockExercise extends Thread {
    static Object object1 = new Object();
    static Object object2 = new Object();
    private boolean loop;

    @Override
    public void run() {
        /**
         * 业务逻辑分析
         * 1.如果flag为T,线程A就会先得到/持有object1对象锁,然后尝试获取object2对象锁
         * 2.如果线程A得不到object2对象锁,就会Blocked
         * 3.如果flag为F,线程B就会先得到/持有object2对象锁
         */
        if (loop) {
            synchronized (object1) {
                System.out.println(Thread.currentThread().getName() + " 1对象出口1");
                synchronized (object2) {
                    System.out.println(Thread.currentThread().getName() + " 2对象出口1");
                }
            }

        } else {
            synchronized (object2) {
                System.out.println(Thread.currentThread().getName() + " 2对象出口2");
                synchronized (object1) {
                    System.out.println(Thread.currentThread().getName() + " 1对象出口2");
                }
            }
        }

    }

    public DeadLockExercise(boolean loop) {
        this.loop = loop;
    }
}

首先在Terminal窗口,Local处

输入jps查看目前运行程序的进程

死锁查询语句
查找到死锁进程号之后,

jstack + 进程号

死锁描述
定位到死锁的原因是A线程上锁,等待B线程释放锁,如此循环等待形成了死锁。

解决简单死锁的方法

死锁的解决要根据产生死锁的条件来进行:
1.针对资源互斥
可以根据代码逻辑去掉互斥锁逻辑,比如涉及金额的话用AtomicInteger(原子操作)、ThreadLocal、CAS乐观锁
2.针对请求与保持条件
可以用List集合将2个资源放在一个集合中,通过contains判断,如果集合中有元素,就用一个boolean变量标记false,直到2个资源释放后,变量标记true后面的线程才能用
3.针对不可剥夺条件
通过this.lock.tryLock(2, TimeUnit.SECONDS);设置时长锁等待

class A extends Thread{
    private final Lock lock = new ReentrantLock(); // 设置锁
    public boolean loop = true;
    public static Object object1 = new Object();
    public static Object object2 = new Object();

    public A(boolean loop){
        this.loop = loop;
        try {
            this.lock.tryLock(2, TimeUnit.SECONDS);// 设置锁等待
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

4.针对循环等待条件
锁排序
比如账户扣钱死锁,可以给账户设置一个id,然后锁对象的时候根据id的大小顺序来锁对象。

5.银行家算法

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

心向阳光的天域

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值