【死锁分享】Java面试官: 请说一个死锁的案例?

简介: 简单案例分享死锁,入门学习!
【辰兮要努力】:hello你好我是辰兮,很高兴你能来阅读,昵称是希望自己能不断精进,向着优秀程序员前行!

博客来源于项目以及编程中遇到的问题总结,偶尔会有读书分享,我会陆续更新Java前端、后台、数据库、项目案例等相关知识点总结,感谢你的阅读和关注,希望我的博客能帮助到更多的人,分享获取新知,大家一起进步!

吾等采石之人,应怀大教堂之心,愿大家奔赴在各自的热爱里…

一、初识死锁

面试官:谈一下你对死锁的理解?
请添加图片描述

死锁就是两个或多个线程(或进程)被无限期地阻塞,相互等待对方手中资源的一种状态

一旦发生了死锁,根据发生死锁的线程的职责不同,就可能会造成 子系统崩溃、性能降低 甚至 整个系统崩溃 等各种不良后果。而且死锁往往发生在高并发、高负载的情况下,因为可能会直接影响到很多用户,造成一系列的问题


Java 死锁产生的四个必要条件:

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

打破死锁即打破如上四个中的一个满足条件即可


二、案例分析

面试官:请简单的写出一个具体的死锁案例!

请添加图片描述

如下两个对象在调度a资源的时候需要调度b资源,同时调度b资源的时候需要调度a资源,资源得不到释放,产生死锁

/**
 * 2021-9-11 15:52:43
 * 辰兮要努力
 */
public class TestDeadLock {
    /*
     * 所谓死锁,是指多个进程在运行过程中因争夺资源而造成的一种僵局,当进程处于这种僵持状态时,若无外力作用,它们都将无法再向前推进
     */

    public static void main(String[] args) {
       //创建两个资源 a资源和b资源互相调度
        final Object a = new Object();
        final Object b = new Object();


       //线程A,按照先锁a再获得锁b的的顺序获得锁
        new Thread() {
            @Override
            public void run(){
                    synchronized (a) {
                        System.out.println(Thread.currentThread().getName()+ "线程 已获取 a资源");

                        try {
                            //线程睡两秒
                            Thread.sleep(2000);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        System.out.println(Thread.currentThread().getName()+ "线程 想获取 b资源");
                        synchronized (b) {
                            System.out.println(Thread.currentThread().getName() + "win");
                        }
                    }
            }
        }.start();

        //线程B先获取锁b再锁a的顺序获得锁
        new Thread() {
            @Override
            public void run(){
                synchronized (b) {
                    System.out.println(Thread.currentThread().getName()+ "线程 已获取 b资源");
                    //线程睡两秒
                    try {
                        Thread.sleep(2000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName()+ "线程 想获取 a资源");
                    synchronized (a) {
                        System.out.println(Thread.currentThread().getName() + "win");
                    }
                }
            }
        }.start();
        
    }
}

执行效果如下
在这里插入图片描述

死锁是指两个或两个以上的进程在执行过程中,由于竞争资源或者由于彼此通信而造成的一种阻塞的现象,若无外力作用,它们都将无法推进下去


三、排查解决

面试官:你如何排查项目中的死锁问题呢?
请添加图片描述

jps(Java Virtual Machine Process Status Tool)

jps是java提供的一个显示当前所有java进程pid的命令,适合在linux/unix平台上简单察看当前java进程的一些简单情况

在这里插入图片描述
输入的效果

C:\Users\lenovo>jps
10608 TestDeadLock
10848 Launcher
6640
18408 Jps
18460 KotlinCompileDaemon

jstack是java虚拟机自带的一种堆栈跟踪工具。

jstack用于生成java虚拟机当前时刻的线程快照。线程快照是当前java虚拟机内每一条线程正在执行的方法堆栈的集合,生成线程快照的主要目的是定位线程出现长时间停顿的原因

C:\Users\lenovo>jstack 10608

输入的效果
在这里插入图片描述

Found one Java-level deadlock:
=============================
"Thread-1":
  waiting to lock monitor 0x0000000003488e08 (object 0x000000076be21938, a java.lang.Object),
  which is held by "Thread-0"
"Thread-0":
  waiting to lock monitor 0x000000000348b698 (object 0x000000076be21948, a java.lang.Object),
  which is held by "Thread-1"

Java stack information for the threads listed above:
===================================================
"Thread-1":
        at com.chenxi.TestDeadLock$2.run(TestDeadLock.java:53)
        - waiting to lock <0x000000076be21938> (a java.lang.Object)
        - locked <0x000000076be21948> (a java.lang.Object)
"Thread-0":
        at com.chenxi.TestDeadLock$1.run(TestDeadLock.java:33)
        - waiting to lock <0x000000076be21948> (a java.lang.Object)
        - locked <0x000000076be21938> (a java.lang.Object)

Found 1 deadlock.

如上的日志
"Thread-1":等待的去锁 <0x000000076be21938>
同时已经锁住了 <0x000000076be21948>

"Thread-0":等待的去锁 <0x000000076be21948>
同时已经锁住了<0x000000076be21938>

Found 1 deadlock.

同时日志里面有产生死锁的类和具体的行数

如上的方法我们可以准确的定位到死锁具体产生的位置,具体的业务场景就根据具体的情况分析解决


非常感谢你阅读到这里,如果这篇文章对你有帮助,希望能留下你的点赞👍 关注❤️ 分享👥 留言💬thanks!!!

愿你们奔赴在自己的热爱里!

目录
相关文章
|
6天前
|
缓存 Java 关系型数据库
【Java面试题汇总】ElasticSearch篇(2023版)
倒排索引、MySQL和ES一致性、ES近实时、ES集群的节点、分片、搭建、脑裂、调优。
【Java面试题汇总】ElasticSearch篇(2023版)
|
6天前
|
设计模式 Java 关系型数据库
【Java笔记+踩坑汇总】Java基础+JavaWeb+SSM+SpringBoot+SpringCloud+瑞吉外卖/谷粒商城/学成在线+设计模式+面试题汇总+性能调优/架构设计+源码解析
本文是“Java学习路线”专栏的导航文章,目标是为Java初学者和初中高级工程师提供一套完整的Java学习路线。
|
6天前
|
设计模式 安全 算法
【Java面试题汇总】设计模式篇(2023版)
谈谈你对设计模式的理解、七大原则、单例模式、工厂模式、代理模式、模板模式、观察者模式、JDK中用到的设计模式、Spring中用到的设计模式
【Java面试题汇总】设计模式篇(2023版)
|
6天前
|
存储 关系型数据库 MySQL
【Java面试题汇总】MySQL数据库篇(2023版)
聚簇索引和非聚簇索引、索引的底层数据结构、B树和B+树、MySQL为什么不用红黑树而用B+树、数据库引擎有哪些、InnoDB的MVCC、乐观锁和悲观锁、ACID、事务隔离级别、MySQL主从同步、MySQL调优
【Java面试题汇总】MySQL数据库篇(2023版)
|
6天前
|
存储 缓存 NoSQL
【Java面试题汇总】Redis篇(2023版)
Redis的数据类型、zset底层实现、持久化策略、分布式锁、缓存穿透、击穿、雪崩的区别、双写一致性、主从同步机制、单线程架构、高可用、缓存淘汰策略、Redis事务是否满足ACID、如何排查Redis中的慢查询
【Java面试题汇总】Redis篇(2023版)
|
6天前
|
缓存 前端开发 Java
【Java面试题汇总】Spring,SpringBoot,SpringMVC,Mybatis,JavaWeb篇(2023版)
Soring Boot的起步依赖、启动流程、自动装配、常用的注解、Spring MVC的执行流程、对MVC的理解、RestFull风格、为什么service层要写接口、MyBatis的缓存机制、$和#有什么区别、resultType和resultMap区别、cookie和session的区别是什么?session的工作原理
【Java面试题汇总】Spring,SpringBoot,SpringMVC,Mybatis,JavaWeb篇(2023版)
|
6天前
|
缓存 Java 数据库
【Java面试题汇总】Spring篇(2023版)
IoC、DI、aop、事务、为什么不建议@Transactional、事务传播级别、@Autowired和@Resource注解的区别、BeanFactory和FactoryBean的区别、Bean的作用域,以及默认的作用域、Bean的生命周期、循环依赖、三级缓存、
【Java面试题汇总】Spring篇(2023版)
|
6天前
|
存储 缓存 监控
【Java面试题汇总】JVM篇(2023版)
JVM内存模型、双亲委派模型、类加载机制、内存溢出、垃圾回收机制、内存泄漏、垃圾回收流程、垃圾回收器、G1、CMS、JVM调优
【Java面试题汇总】JVM篇(2023版)
|
6天前
|
存储 缓存 安全
【Java面试题汇总】多线程、JUC、锁篇(2023版)
线程和进程的区别、CAS的ABA问题、AQS、哪些地方使用了CAS、怎么保证线程安全、线程同步方式、synchronized的用法及原理、Lock、volatile、线程的六个状态、ThreadLocal、线程通信方式、创建方式、两种创建线程池的方法、线程池设置合适的线程数、线程安全的集合?ConcurrentHashMap、JUC
【Java面试题汇总】多线程、JUC、锁篇(2023版)
|
6天前
|
安全 Java API
【Java面试题汇总】Java基础篇——String+集合+泛型+IO+异常+反射(2023版)
String常量池、String、StringBuffer、Stringbuilder有什么区别、List与Set的区别、ArrayList和LinkedList的区别、HashMap底层原理、ConcurrentHashMap、HashMap和Hashtable的区别、泛型擦除、ABA问题、IO多路复用、BIO、NIO、O、异常处理机制、反射
【Java面试题汇总】Java基础篇——String+集合+泛型+IO+异常+反射(2023版)