【JavaEE】死锁问题 -- 多线程篇(5)

死锁问题

  • [1. 死锁是什么?](#1. 死锁是什么?)
  • [2. 如何避免死锁?](#2. 如何避免死锁?)

1. 死锁是什么?

概念

  • 死锁是这样一种情形: 多个线程同时被阻塞, 它们中的一个或者全部都在等待某个资源被释放, 由于线程被无限期的阻塞, 因此程序不能正常终止。

死锁的三种常见的场景

  1. 一个线程, 一把锁, 但是是不可重入锁, 该线程针对这个锁连续加锁两次, 就会出现死锁;

  2. 两个线程, 两把锁, 这两个线程先分别获取一把锁, 然后在同时尝试获取对方的锁;

  3. N个线程M把锁

为了进一步阐述死锁的形成, 很多资料上也会谈论到 "哲学家就餐问题".

  • 有个桌子, 围着一圈 哲 ♂ 家, 桌子中间放着一盘意大利面. 每个哲学家两两之间, 放着一根筷子.

  • 每个 哲 ♂ 家 只做两件事: 思考人生 或者 吃面条. 思考人生的时候就会放下筷子. 吃面条就会拿起左右两边的筷子(先拿起左边, 再拿起右边).

  • 如果 哲 ♂ 家 发现筷子拿不起来了(被别人占用了), 就会阻塞等待.

  • 关键点在这 假设同一时刻, 五个 哲 ♂ 家 同时拿起左手边的筷子, 然后再尝试拿右手的筷子, 就会发现右手的筷子都被占用了. 由于 哲 ♂ 家 们互不相让, 这个时候就形成了 死锁

2. 如何避免死锁?

死锁产生的四个必要条件 -- 只要破坏其中一个即可

  1. 互斥使用, 即当资源被一个线程使用(占用)时, 别的线程不能使用
    • 实际使用的锁, 一般都是互斥的(锁的基本特性)
  2. 不可抢占, 资源请求者不能强制从资源占有者手中夺取资源, 资源只能有资源占有者主动释放
    • 这也是锁的基本特性
  3. 请求和保持, 即当资源请求者在请求其它资源的同时保持对原有资源的占有
    • 取决于代码结构, 不好被修改, 修改的话可能会影响到需求
  4. 循环等待, 即存在一个瞪大队列: P1占有P3资源, P3占有P1的资源, 这样就形成了一个等待回路
    • 取决于代码结构, 一般都是打破这个条件来解决死锁的问题

解决死锁问题的的方法

  • 银行家算法
    • 可以解决死锁问题, 就是不接地气
  • 简答并且非常有效的解决死锁的方法
    • 针对锁进行编号, 并且规定加锁的顺序
      • 例如, 约定, 每个线程如果要获取多把锁, 必须先获取 编号小的锁, 后获取编号大的锁
      • 只要所有线程加锁的顺序, 都严格遵守上述顺序, 就一定不会出现循环瞪大
相关推荐
黑马师兄11 分钟前
RAG混合检索深度解析:让AI真正找到你要的内容
java·人工智能·ai·agent·rag·ai-native
码客日记15 分钟前
Spring Boot 配置文件敏感信息加密(Jasypt 企业级完整方案)
java·spring boot·git
凡人叶枫1 小时前
Effective C++ 条款04:确定对象被使用前已先被初始化
java·linux·开发语言·c++·嵌入式开发
极客先躯1 小时前
高级java每日一道面试题-2026年02月01日-实战篇[Docker]-Docker Volume 的生命周期管理是怎样的?
java·运维·docker·容器·持久化·架构图·容器卷
NE_STOP1 小时前
Raft算法处理细节
java
努力攻坚操作系统1 小时前
编程语言编译运行机制对比:C / Java / Python
java·c语言·python
慧一居士1 小时前
对比两个文件内容是否完全一致,java实现示例
java
再写一行代码就下班2 小时前
Cursor配置Java环境、创建Spring Boot项目的步骤
java·开发语言·spring boot
摇滚侠2 小时前
Java 零基础全套教程,类的加载过程与类加载器的理解,笔记 189
java·后端·intellij-idea
kong@react2 小时前
Rocky Linux 10.2 全面解析:企业级 CentOS 替代方案及保姆级docker安装
java·linux·运维·docker