首页 > 其他分享 >手画图解,关于死锁,面试的一切都在这里了

手画图解,关于死锁,面试的一切都在这里了

时间:2022-12-27 17:32:10浏览次数:50  
标签:转账 事务 请求 进程 死锁 手画 图解 资源

什么是死锁(Deadlock)

死锁是指两个或两个以上的线程在执行过程中,因争夺资源而造成的一种互相等待的现象。若无外力作用,它们都将无法推进下去。

手画图解,关于死锁,面试的一切都在这里了_面试

产生死锁的四个必要条件得烂熟于心:

  • 互斥条件:进程要求对所分配的资源进行排他性控制,即在一段时间内某资源仅为一个进程所占用。此时若有其他进程请求该资源,则请求进程只能等待。
  • 不剥夺条件:进程所获得的资源在未使用完毕之前,不能被其他进程强行夺走,即只能由获得该资源的进程自己来释放。
  • 请求和保持条件:进程已经保持了至少一个资源,但又提出了新的资源请求,而该资源已被其他进程占有,此时请求进程被阻塞,但对自己已获得的资源保持不放。
  • 循环等待条件:存在一种进程资源的循环等待链,连中每一个进程已获得的资源同时被链中下一个进程所请求。

相应的,如果想在程序运行之前预防发生死锁(也成为 “死锁预防”),必须设法破坏产生死锁的四个必要条件之一

  • 破坏互斥条件:允许系统资源都能共享使用,则系统不会进行死锁状态。这种方案并不太可行,因为有些资源根本就不能同时访问,比如打印机。
  • 破坏不剥夺条件:当一个已经保持了某些不可剥夺资源的进程,请求新的资源时得不到满足,它必须释放已经保持的所有资源,待以后需要时再重新申请。这种方法常用于状态易于保存和恢复的资源,如 CPU 的寄存器及内存资源,一般不能用于打印机之类的资源。
  • 破坏请求和保持条件:采用预先静态分配方法,即进程在运行前一次申请完他所需要的全部资源,在他的资源未满足前,不把它投入运行。一旦运行后,这些资源就一直归它所有,也不再提出其他资源请求,这样就可以保证系统不会发生死锁。
  • 破坏循环等待条件:采用顺序资源分配法。首先给系统中的资源编号,规定每个进程,必须按编号递增的顺序请求资源,同类资源一次申请完。也就是说,只要进程提出申请分配资源,则该进程在以后的资源申请中,只能申请编号比之前大的资源

光看罗列出来的几点文字肯定还是不能完全理解,下面会结合实例来给大伙解释。

用 Java 写一个死锁

这绝对是面试中 Java 手写题的 TOP2!!!除了人尽皆知的手写单例模式,手写死锁可能有些小伙伴会遗漏掉。

逻辑其实非常简单,我们申请两个资源,开两个线程,每个线程持有其中的一个资源,并且互相请求对方的资源,就构成了死锁。

手画图解,关于死锁,面试的一切都在这里了_面试_02

MySQL 死锁

MySQL 经典的死锁案例

下面来看个 MySQL 经典的死锁案例:转账

A 账户给 B 账户转账 50 元的同时,B 账户也给 A 账户转账 30 元

手画图解,关于死锁,面试的一切都在这里了_后端_03

正常情况下,如果只有一个操作,A 给 B 转账 50 元,可以在一个事务内完成,先获取 A 用户的余额和 B 用户的余额,因为之后需要修改这两条数据,所以需要通过写锁(for UPDATE)锁住他们,防止其他事务更改导致我们的更改丢失而引起脏数据

手画图解,关于死锁,面试的一切都在这里了_面试_04

但如果 A 给 B 转账和 B 给 A 转账同时发生,那就是两个事务,可能发生死锁:

手画图解,关于死锁,面试的一切都在这里了_面试_05

1)A 用户给 B 用户转账 50 元,需在程序中开启事务 1 来执行 SQL,获取 A 的余额同时锁住 A 这条数据。

手画图解,关于死锁,面试的一切都在这里了_春招_06

2)B 用户给 A 用户转账 30 元,需在程序中开启事务 2 来执行 SQL,并获取 B 的余额同时锁住 B 这条数据。

手画图解,关于死锁,面试的一切都在这里了_春招_07

3)在事务 1 中执行剩下的 SQL,此时事务 1 是获取不到 B 的锁的,也即 select for update 就会被阻塞住;

手画图解,关于死锁,面试的一切都在这里了_后端_08

4)同理,事务 2 继续执行剩下的 SQL,请求 A 的锁,也是获取不到的

事务 1 和事务 2 存在相互等待获取锁的过程,导致两个事务都挂起阻塞,最终抛出获取锁超时的异常。

手画图解,关于死锁,面试的一切都在这里了_秋招_09

如何解决 MySQL 死锁

要想解决上述死锁问题,我们可以从死锁的四个必要条件入手。

指导思想其实很明确:就是保证 A 向 B 转账和 B 向 A 转账这两个事务同一时刻只能有一个事务能成功获取到锁

由于互斥不剥夺是锁本质的功能体现,无法修改,所以咱们从另外两个条件尝试去解决。

1)破坏 “请求和保持” 条件:A 和 B 之间的操作用同一个锁锁住(比如用 Redis 分布式锁做,A 和 B 之间的锁的 key 表示为 ​​A:B​​,可以让 id 小的用户排在前面,id 大的用户排在后面,这样来设计 key。如果存在分库分表的情况,用 hashcode 来做比较也行),保证 A 向 B 转账和 B 向 A 转账这两个事务同一时刻只能有一个事务能成功获取锁

手画图解,关于死锁,面试的一切都在这里了_秋招_10

2)破坏 “循环等待” 条件:先获取更小的锁,获取到了小的锁才能获取大锁(所谓小锁还是大锁,也可以简单的根据用户的 id 来进行区分,先请求用户 id 较小的,再请求用户 id 较大的)。比如 A.id < B.id,那么 A 和 B 之间的操作,都是要先获取 A 锁,再获取 B 锁

手画图解,关于死锁,面试的一切都在这里了_面试_11

具体代码可参考如下:

手画图解,关于死锁,面试的一切都在这里了_春招_12


小伙伴们大家好呀,本文首发于公众号@飞天小牛肉,阿里云 & InfoQ 签约作者,分享大厂面试原创高质量题解、原创技术干活和成长经验~)



标签:转账,事务,请求,进程,死锁,手画,图解,资源
From: https://blog.51cto.com/u_15177525/5973099

相关文章

  • 我对《Mysql死锁排查:insert on duplicate死锁一次排查分析过程 - 少说点话 - 博客园》
    原文在这里:Mysql死锁排查:insertonduplicate死锁一次排查分析过程 比较菜,看了一遍还是不懂死锁是怎么形成的。绕了很多圈才全理解。特此记录。 关于mysql版本我先......
  • CentOS 6.0 图形(图解)安装教程、基本配置、网络配置、软件源配置、安装压
    一.准备安装CentOS61.CentOS简介CentOS是甚么?CentOS是一个基于RedHat企业级Linux提供的可自由使用的源代码企业级的Linux发行版本。每个版本的CentOS都会获得七年......
  • 图解Http协议 url长度限制
     http请求报文的格式一般请求所带有的属性: http响应报文的格式:响应首部一般包含如下内容:   一、技术基石及概述问:什么是HTTP?答:HTTP是一个客户端和服务器端请求和响......
  • 一文帮你详细图解二进制、八进制、十进制、十六进制之间的转换
    1、背景(Contexts)之前使用SQL把十进制的整数转换为三十六进制,SQL代码请参考:SQLServer进制转换函数,其实它是基于二、八、十、十六进制转换的计算公式的,进制之间的转换是很基......
  • 图解数据库左连接、右连接、内连接、外连接、全连接
    1.前言在日常的数据库增删改查任务中,由于数据的规范设计,数据通常不集中在同一张表里,所以经常会涉及到多表的数据查询,多表数据查询需要表之间的连接,而表间连接方式有很多,......
  • [ Linux ] 死锁以及如何避免死锁
    1.什么是死锁?死锁死锁是指在一组进程中的各个进程均占有不会释放的资源,但因互相申请被其他进程所占用不会释放的资源而处于的一种永久等待的状态。2.模拟死锁情况我们使用多......
  • 记一次生产环境死锁问题分析
    记一次生产环境死锁问题分析一、问题背景最近在做的项目中生产环境频繁出现数据库死锁的问题,解决一个,又来一个,最后数据库不死锁了,多了个请求文件服务器永久阻塞的问题,也是折......
  • 图解排序算法,这五种最热门!
    介绍5种热门的排序算法,用图文+代码的方式讲解~说到排序算法,大家估计都比较熟悉,但要你一下子写出来又蒙圈了。所以这篇文章不会讲解所有的排序算......
  • 技术分享 | 死锁分析案例
    高鹏 爱可生开源社区 2019-08-16作者:高鹏 文章末尾有他著作的《深入理解MySQL主从原理32讲》,深入透彻理解MySQL主从,GTID相关技术知识。一、问题由来这是我同事问我的一......
  • 故障分析 | MySQL死锁案例分析
    一 背景死锁,其实是一个很有意思也很有挑战的技术问题,大概每个DBA和部分开发同学都会在工作过程中遇见过。本次分享的死锁案例更新不存在的记录加上XGAPlock和inser......