手把手教学轻松带你排查Java程序死锁问题(泰坦尼克号剧情版)

《泰坦尼克号》想必这么多年过去了依旧是无数人心目中的经典,不知有多少人,因为露丝与杰克的爱情故事而流泪,尤其是杰克为了让露丝能够安稳地活下去,自己甘愿献出生命,最终在冰冷的海水里,被活活地冻死。而露丝在多年后嫁为人妇,幸福地度过了后半生,完成了杰克的临终遗愿。

意外小插曲:爱情有时让人心情甜美但又充满磕磕碰碰。露丝和杰克都是鸭霸王的超级粉,下午露丝和杰克在船头夹板上嬉戏,露丝提议让杰克去餐厅打包一份鸭霸王。杰克打包"鸭霸王"的时候服务员只给了一双筷子。但杰克没有注意到,就屁颠屁颠的跑了夹板。问题来了只有一双筷子两个人怎么吃呢?


露丝和杰克嘴角同一时刻都露出了一丝狡黠的笑意,同时提议说到:那我们模仿微信抢红包,拼手速,谁先拿到谁先吃。那么此刻会出现如下3种情况:
1、露丝先拿到2只筷子,并开心的吃起了鸭霸王 (露丝胜利)
2、杰克先拿到2只筷子,并开心的吃起了鸭霸王 (杰克胜利)
3、杰克和露丝各拿到了一只筷子,他们都很想吃,互不相让。(阻塞产生死锁)

一、产生死锁的条件

(1) 互斥条件:一个资源每次只能被一个进程使用。
(2) 请求与保持条件:一个进程因请求资源而阻塞时,对已获得的资源保持不放。
(3) 不剥夺条件:进程已获得的资源,在末使用完之前,不能强行剥夺。
(4) 循环等待条件:若干进程之间形成一种头尾相接的循环等待资源关系。

这四个条件是死锁的必要条件,只要系统发生死锁,这些条件必然成立,而只要上述条件之一不满足,就不会发生死锁。

二、模拟死锁问题

(1) 程序模拟死锁

package com.demo.lock;

/**
 * @author youyun.xu
 * @ClassName: DeadLock
 * @Description: 程序模拟死锁
 * @date 2021/2/2 19:09
 */
public class DeadLock {

    public static void main(String[] args) {
        DeadLock deadLock = new DeadLock();
        deadLock.titanic();

    }

    public void titanic(){
        /*
        * 死锁模拟场景:杰克和露丝各拿到了一只筷子,他们都很想吃,互不相让。(阻塞产生死锁)
        * */
        Thread jack = new Thread( new Jack(),"杰克");
        Thread rose = new Thread( new Rose(),"露丝");
        jack.start();
        rose.start();
    }

    //总共2根筷子[chopsticks1、chopsticks2]
    Object chopsticks1 = new Object();
    Object chopsticks2 = new Object();

    class Jack implements Runnable{
        @Override
        public void run() {
            synchronized (chopsticks1) {//杰克抢到了第1根筷子,开心的不要不要的
                System.out.println(Thread.currentThread().getName().concat(" -> 抢到了第一根筷子"));
                sleep();
                synchronized (chopsticks2) {//第2根筷子被“露丝”抢走,杰克在焦急等待,但露丝此刻没有丝毫想让出来的意思,因为她都很想吃鸭霸王。
                    System.out.println(Thread.currentThread().getName().concat(" -> 抢到了第二根筷子"));
                    sleep();
                }
            }
        }

        public void sleep(){
            try {
                Thread.sleep(500);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    class Rose implements Runnable{
        @Override
        public void run() {
            synchronized (chopsticks2) { //露丝抢到了第2根筷子,开心的不要不要的
                System.out.println(Thread.currentThread().getName().concat(" -> 抢到了第二根筷子"));
                sleep();
                synchronized (chopsticks1) {//第1根筷子被“杰克”抢走,露丝在焦急等待,但“杰克”此刻没有丝毫想让出来的意思,因为他都很想吃鸭霸王。
                    System.out.println(Thread.currentThread().getName().concat(" -> 抢到了第一根筷子"));
                }
            }
        }

        public void sleep(){
            try {
                Thread.sleep(500);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

(2) 程序模拟运行截图

三、系统如何排查死锁

Jconsole它是JDK自带的图形化界面工具,使用JDK给我们的的工具JConsole,本次就通过它排查死锁。

1、打开cmd然后输入Jconsole打开

2、与Jconsole 建立链接

3、点击检查死锁,并查看检查结果

四、思考题

1、杰克和露丝各拿到了一只筷子,他们都很想吃,互不相让(阻塞产生死锁),如果你是中国版的杰克你该怎么做呢?

2、既然我们知道死锁产生的条件、同时用程序模拟观察了死锁的产生过程,请问该如何解决死锁问题?

当你觉得一切都为时已晚的时候,其实恰恰是最早的时候。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

热情的码农

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

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

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

打赏作者

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

抵扣说明:

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

余额充值