三分钟,大白话聊聊死锁的本质和解决方案

聊聊死锁的本质及避免

在复杂并发程序中,国外大神Lu对MySQL、Apache、Office等常用软件做了一项并发漏洞调查,30%是有关死锁的缺陷。

本篇就聊聊死锁产生的本质,以及站在巨人的肩膀上俯瞰在避免死锁的问题,前人给出了哪些方案。(只聊思想)

死锁是个啥

现看个简单例子:当线程1持有锁2,正在请求另一个锁2;线程2持有锁1,接着请求获得锁2。这个时候死锁就产生了。以下伪码可能出现上述场景

为啥出现死锁

通过上面例子可知,加锁顺序的不一致是死锁的诱因。再说通俗一点就是两个线程都在等待对方持有的锁资源被释放,都在互相等待你的资源,干瞪眼了。这就是我对死锁产生原因的理解。

当然,国外经典教材《操作系统导论》也对死锁产生的条件给出了权威的论点 如下:

  • 互斥:线程对于需要的资源进行互斥的访问(例如线程获得一个锁)
  • 持有并等待:线程持有了资源,同时又在等待其他资源(例如需要获得一个锁)
  • 非抢占:线程获得资源(例如锁),不能被抢占
  • 循环等待:线程之间存在一个环路,环路上每个线程都额外持有一个资源,而这个资源又是下一个线程要申请的。(就是加锁顺序)

对于死锁发生,上述4点缺一不可

如何预防死锁?

既然知道了死锁的几点原因,那我们只需对症下药即可

保证加锁顺序一致

其目的就是让代码不会产生循环等待。

比如对于一个并发操作需要获得A,B,C三把锁。我们约定,每次操作都必须先申请A锁,再申请B锁,最后申请C锁。

实际上,数据库的常见死锁都是因为加锁顺序不一致导致的。比如MySQL间隙锁,10~20。有时候会

适当避免互斥操作

一种思想是想要避免并发操作潜在的死锁,我就让整个操作无锁化不就万事大吉!!!

通过强大的硬件指令,CAS可以构建各种原子操作,无锁数据结构。例如Java的Atomic包,著名无锁队列Disruptor。

有点扯淡的银行家算法---通过调度避免死锁

首先要明白一个道理,死锁是建立多核cpu上。单核CPU是不会发生死锁的。

参考如下,因为线程1,2不存在并发执行,即使两个线程加锁顺序不一致,也不会导致死锁

现在举一个2核 ,4线程加锁的例子,助你理解银行家算法的本质。看看如下表格

线程对于锁的需求

线程1 线程2 线程3 线程4
Lock1 yes yes no no
Lock2 yes yes yes no

想要避免死锁,一种聪明的调度方式就是让同时需要Lock1和Lock2的线程1,线程2无法并发执行,也就是让他们在同一个核上运行。cpu调度如下:

银行家算法的缺点

遗憾的是,银行家算法不能充分利用多核CPU的性能。

试想一下,假设线程1、2、3、4都需要Lock1、Lock2,最后的调度就是所有线程都在一个CPU上,所以局限性还是蛮大的。因此银行家算法的调度也不是主流的方案。

小结

实际上在开发过程中,我们在业务代码务必保证加锁的顺序,是预防死锁的最佳方案。

还有一种更为常用的策略,就是死锁偶尔发生了。系统需要提供死锁检测和恢复技术,常见的数据库都提供了。如果还有一些简单的死锁现象,也可以人工参与。大家解决MySQL死锁不都这样的吗?

我是爱聊技术的山人,大伙下期再见!!!

相关推荐
一路向北⁢几秒前
APP企业级业务数据埋点系统(基于 Spring Boot & ClickHouse)
spring boot·后端·clickhouse·统计分析·埋点·pu·vu
老蒋每日coding4 分钟前
Go语言实现 Agent Demo
开发语言·后端·golang
那我掉的头发算什么13 分钟前
【SpringBoot】从学会使用maven开始
spring boot·后端·spring·maven
老蒋每日coding21 分钟前
Go语言面试题及答案总结(一)
面试·职场和发展·golang
sunnyday042623 分钟前
Spring Boot 中的优雅重试机制:从理论到实践的完整指南
java·spring boot·后端
xiaoxue..26 分钟前
Zustand 状态管理:轻量高效的 React 状态解决方案✨
前端·react.js·面试·状态模式·zustand
找不到、了27 分钟前
Spring Boot 高并发架构:五层并发限制模型
spring boot·后端·架构
正在走向自律33 分钟前
时序数据管理:金仓数据库破局之道
java·后端·struts·时序数据库·金仓kes v9
moxiaoran575339 分钟前
springboot多模块项目构建docker镜像
spring boot·后端·docker
小北方城市网41 分钟前
SpringBoot 集成消息队列实战(RabbitMQ/Kafka):异步通信与解耦,落地高可靠消息传递
java·spring boot·后端·python·kafka·rabbitmq·java-rabbitmq