死锁场景模拟

本文介绍了死锁的四个必要条件,并通过Java代码模拟了一个死锁场景。提出了预防死锁的策略,包括资源预先分配和有序分配资源。最后展示了如何通过改变代码结构避免死锁,通过设置任务一次性申请所有所需资源来破坏占用并等待条件。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

发生死锁的四个必要条件:

  • 互斥条件:进程要求对所分配的资源进行排它性控制,即在一段时间内某资源仅为一进程所占用。
  • 请求和保持条件:当进程因请求资源而阻塞时,对已获得的资源保持不放。
  • 不剥夺条件:进程已获得的资源在未使用完之前,不能剥夺,只能在使用完时由自己释放。
  • 环路等待条件:在发生死锁时,必然存在一个进程–资源的环形链。

预防死锁的方法:

理解了死锁的原因,尤其是产生死锁的四个必要条件,就可以最大可能地避免、预防和解除死锁。只要打破四个必要条件之一就能有效预防死锁的发生:

  • 打破互斥条件:改造独占性资源为虚拟资源,大部分资源已无法改造。
  • 打破不可抢占条件:当一进程占有一独占性资源后又申请一独占性资源而无法满足,则退出原占有的资源。
  • 打破占有且申请条件:采用资源预先分配策略,即进程运行前申请全部资源,满足则运行,不然就等待,这样就不会占有且申请。
  • 打破循环等待条件:实现资源有序分配策略,对所有设备实现分类编号,所有进程只能采用按序号递增的形式申请资源。

模拟发生死锁场景:

public class DeadLock {
    
    public static String resource1 = "resource-1";
    public static String resource2 = "resource-2";

    public static void main(String[] args) {
        Thread thread1 = new Thread(new TaskA());
        Thread thread2 = new Thread(new TaskB());
        thread1.start();
        thread2.start();
    }
    static class TaskA implements Runnable {
        @Override
        public void run() {
            try{
                System.out.println("TaskA启动");
                while(true){
                    synchronized(DeadLock.resource1){
                        System.out.println("TaskA拿到了resource-1的锁");
                        Thread.sleep(3000);
                        //获取resource1后先等一会儿,让TaskB有足够的时间锁住resource2
                        System.out.println("TaskA想拿resource-2的锁。。。。");
                        synchronized(DeadLock.resource2){
                            System.out.println("TaskA获得到了resource-2的锁");
                        }
                    }
                }
            }catch(Exception e){
                e.printStackTrace();
            }
        }
    }
    static class TaskB implements Runnable {
        @Override
        public void run(){
            try{
                System.out.println("TaskB启动");
                while(true){
                    synchronized(DeadLock.resource2){
                        System.out.println("TaskB拿得到了resource-2的锁");
                        Thread.sleep(3000);
                        //获取resource2后先等一会儿,让TaskA有足够的时间锁住resource1
                        System.out.println("TaskB想拿resource-1的锁。。。。");
                        synchronized(DeadLock.resource1){
                            System.out.println("TaskB获得到了resource-1的锁");
                        }
                    }
                }
            }catch(Exception e){
                e.printStackTrace();
            }
        }
    }
}

在这里插入图片描述

使用jstack检测死锁:

  • 先使用jps命令查出应用的端口号:
    在这里插入图片描述

  • 在使用jstack命令查出进程的堆栈信息:

在这里插入图片描述

解决方法:

通过设置某些限制条件,去破坏产生死锁的四个必要条件中的一个或几个条件,来防止死锁的发生。

破坏占用并等待条件,预防死锁,即在任务开始的时候,就申请所有的资源。

public class DeadLock {

    static Object o1 = new Object();
    static Object o2 = new Object();

    public static void main(String[] args) {
        Thread t1 = new Thread(new TaskA());
        Thread t2 = new Thread(new TaskB());
        t1.start();
        t2.start();
    }
}

class TaskA implements Runnable {

    @Override
    public void run() {
        synchronized (DeadLock.class) {
            synchronized (DeadLock.o1) {
                System.out.println(Thread.currentThread().getName() + "拿到了o1资源");
                try {
                    Thread.sleep(1000);
                    synchronized (DeadLock.o2) {
                        System.out.println(Thread.currentThread().getName() + "拿到了o2资源");
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

class TaskB implements Runnable {

    @Override
    public void run() {
        synchronized (DeadLock.class) {
            synchronized (DeadLock.o2) {
                System.out.println(Thread.currentThread().getName() + "拿到了o2资源");
                try {
                    Thread.sleep(1000);
                    synchronized (DeadLock.o1) {
                        System.out.println(Thread.currentThread().getName() + "拿到了o1资源");
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

测试结果:
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值