什么是死锁 , 以及产生的原因详细介绍

死锁

一. 什么是死锁

指的是两个或者两个以上的线程在执行的过程中由于竞争同步锁而产生的一种阻塞现象;如果没有外力的作用,他们将无法继续执行下去,这种情况称之为死锁,

通俗的说死锁产生的原因主要是由于线程的相互等待 , 导致程序无法进行下去

二. 代码阐述

这里我们写一段代码对死锁进行描述, 阐述其中的原理

  1. LockA类 --> 设置线程

    public class LockA {
        public static LockA lockA = new LockA();
    }
    
    
  2. LockB类 --> 设置线程

    public class LockB {
        public static LockB lockB = new LockB();
    }
    
  3. DieLock类 --> 继承Runnable重写run方法

    public class DieLock implements Runnable{
        private boolean flag;
    
        public DieLock(boolean flag) {
            this.flag = flag;
        }
    
        @Override
        public void run() {
            if (flag){
                synchronized (LockA.lockA){
                    System.out.println("if...lockA");
                    synchronized (LockB.lockB){
                        System.out.println("if...lockB");
                    }
                }
            }else{
                synchronized (LockB.lockB){
                    System.out.println("else...lockB");
                    synchronized (LockA.lockA){
                        System.out.println("else...lockA");
                    }
                }
            }
        }
    }
    
    
  4. Test01类 --> 实现类

    public class Test01 {
        public static void main(String[] args) {
            DieLock dieLock1 = new DieLock(true);
            DieLock dieLock2 = new DieLock(false);
    
            new Thread(dieLock1).start();
            new Thread(dieLock2).start();
        }
    }
    
    

在这里插入图片描述

场景描述

假设有两个线程 Thread1Thread2,它们分别通过不同的构造函数参数初始化了 DieLock 对象:

  • Thread1 初始化了 DieLock 对象,其中 flagtrue
  • Thread2 初始化了 DieLock 对象,其中 flagfalse

执行流程

  1. Thread1 执行

    • 首先获取 LockA.lockA 锁。
    • 然后尝试获取 LockB.lockB 锁。
  2. Thread2 执行

    (几乎同时或稍后):

    • 首先获取 LockB.lockB 锁(因为 flagfalse)。
    • 然后尝试获取 LockA.lockA 锁。

死锁发生

  • Thread1 已经持有 LockA.lockA 锁,并正在等待 LockB.lockB 锁。
  • Thread2 已经持有 LockB.lockB 锁,并正在等待 LockA.lockA 锁。

由于两个线程都在等待对方释放它们需要的锁,它们都将无限期地等待下去,从而导致了死锁。

在这里由于synchronized 控制的是整个代码块 , 当程序执行完毕才会释放此时占有lockA锁

synchronized (LockA.lockA){
                System.out.println("if...lockA");
                synchronized (LockB.lockB){
                    System.out.println("if...lockB");
                }
            }

同理Thread2占有lockB锁 , 然而此时Thread1线程中LockA在等待LockB , Thread2线程中LockB 在等待LockA就会产生死锁

如果我们稍作修改 , 将Thread2 的第二层嵌套取消掉就会发现运行结果不一样了 , 死锁问题不会产生

此时Thread2在获得LockB之后运行完毕释放LockB , Thread1也能获取到LockB进而继续执行

public class DieLock implements Runnable{
    private boolean flag;

    public DieLock(boolean flag) {
        this.flag = flag;
    }

    @Override
    public void run() {
        if (flag){
            synchronized (LockA.lockA){
                System.out.println("if...lockA");
                synchronized (LockB.lockB){
                    System.out.println("if...lockB");
                }
            }
        }else{
            synchronized (LockB.lockB){
                System.out.println("else...lockB");
                
                }
            }
        }
    }
}

在这里插入图片描述

  • 34
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

攒了一袋星辰

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

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

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

打赏作者

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

抵扣说明:

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

余额充值