死锁是什么?死锁是如何产生的?如何破除死锁?
1. 死锁是什么
多个线程同时被阻塞,它们中的一个或者全部都在等待某个资源被释放。由于线程被无限期地阻塞,因此程序不可能正常终止。
2. 死锁的三种典型情况
-
一个线程, 一把锁, 是不可重入锁, 该线程针对这个锁连续加锁两次, 就会出现死锁.
-
两个线程, 两把锁, 让两个线程先分别获取到一把锁, 然后再同时尝试获取对方的锁.
- 假如A和B去吃饺子, A先拿起了酱油碟, B先拿起了醋碟. 此时A说’你先把醋给我, 我用完了就把酱油给你’, B说’你先把酱油给我, 用完了再把醋给你’
- 如果两个人互不相让, 就产生了死锁.
- 酱油和醋相当于是两把锁, 这两个人就是两个线程.
-
N个线程M把锁
-
“哲学家就餐问题”
-
有个桌子, 围着一圈哲学家, 桌子中间放着一盘意大利面. 每个哲学家两两之间, 放着一根筷子.

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

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

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

-
3. 死锁产生的必要条件
死锁产生的四个必要条件:
-
互斥使用,即当资源被一个线程使用(占有)时,别的线程不能使用
-
不可抢占,资源请求者不能强制从资源占有者手中夺取资源,资源只能由资源占有者主动释放。
-
请求和保持,即当资源请求者在请求其他的资源的同时保持对原有资源的占有。一个线程去尝试获取多把锁, 在获取第二八所的过程中, 保持对第一把锁的获取状态.
-
循环等待,即存在一个等待队列:P1占有P2的资源,P2占有P3的资源,P3占有P1的资源。这样就形成了一个等待环路
当上述四个条件都成立的时候,便形成死锁。当然,死锁的情况下如果打破上述任何一个条件,便可让死锁消失。
最容易破坏的就是 “循环等待”.
4. 如何解决死锁
破坏循环等待
最常用的一种死锁阻止技术就是锁排序. 假设有 N 个线程尝试获取 M 把锁, 就可以针对 M 把锁进行编号(1, 2, 3…M).
N 个线程尝试获取锁的时候, 都按照固定的按编号由小到大顺序来获取锁. 这样就可以避免环路等待.
还是上述的哲学家就餐问题. 2号人拿起1号筷子, 3号人拿起2号筷子…

到了1号人, 按照编号由小到大顺序来获取锁, 他应该拿起1号筷子, 但是当前1号筷子被占用了, 那么1号人就陷入了阻塞状态

这样5号人就可以拿起4, 5两根筷子, 当他吃完, 4号筷子被释放; 4号人也可以使用3, 4两根筷子, 然后释放…直到2号人释放了1, 2两个筷子, 1号人就能使用1号筷子了.
于是就不会产生循环等待了
两个线程对于加锁的顺序没有约定, 就容易产生环路等待.
Object lock1 = new Object();
Object lock2 = new Object();
Thread t1 = new Thread() {@Overridepublic void run() {synchronized (lock1) {synchronized (lock2) {// do something...}}}
};
t1.start();
Thread t2 = new Thread() {@Overridepublic void run() {synchronized (lock2) {synchronized (lock1) {// do something...}}}
};
t2.start();
约定好先获取 lock1, 再获取 lock2 , 就不会环路等待.
Object lock1 = new Object();
Object lock2 = new Object();
Thread t1 = new Thread() {@Overridepublic void run() {synchronized (lock1) {synchronized (lock2) {// do something...}}}
};
t1.start();
Thread t2 = new Thread() {@Overridepublic void run() {synchronized (lock1) {synchronized (lock2) {// do something...}}}
};
t2.start();
相关文章:
死锁是什么?死锁是如何产生的?如何破除死锁?
1. 死锁是什么 多个线程同时被阻塞,它们中的一个或者全部都在等待某个资源被释放。由于线程被无限期地阻塞,因此程序不可能正常终止。 2. 死锁的三种典型情况 一个线程, 一把锁, 是不可重入锁, 该线程针对这个锁连续加锁两次, 就会出现死锁. 两个线程…...
给虚拟机配置静态id地址
1.令人头大的原因 当连接虚拟机的时候 地址不一会就改变,每次都要重新输入 2.配置虚拟机静态id地址 打开命令窗口执行 : vim /etc/sysconfig/network-scripts/ifcfg-ens33 按下面操作修改 查看自己子网掩码 3.重启网络 命令行输入 systemctl restart netwo…...
Mybatis-Plus 租户使用
Mybatis-Plus 租户使用 文章目录 Mybatis-Plus 租户使用一. 前言1.1 租户存在的意义1.2 租户框架 二. Mybatis-plus 租户2.1 租户处理器2.2 前置准备1. 依赖2. 表及数据准备3. 代码生成器 2.3 使用 三. 深入使用3.1 前言3.2 租户主体设值,取值3.3 部分表全量db操作3…...
vue el-table (固定列+滚动列)【横向滚动条】确定滚动条是在列头还是列尾
效果图: 代码实现: html: <script src"//unpkg.com/vue2/dist/vue.js"></script> <script src"//unpkg.com/element-ui2.15.14/lib/index.js"></script> <div id"app" style&quo…...
⑦【Redis GEO 】Redis常用数据类型:GEO [使用手册]
个人简介:Java领域新星创作者;阿里云技术博主、星级博主、专家博主;正在Java学习的路上摸爬滚打,记录学习的过程~ 个人主页:.29.的博客 学习社区:进去逛一逛~ Redis GEO ⑦Redis GEO 基本操作命令1.geoadd …...
LeetCode 2304. 网格中的最小路径代价:DP
【LetMeFly】2304.网格中的最小路径代价:DP 力扣题目链接:https://leetcode.cn/problems/minimum-path-cost-in-a-grid/ 给你一个下标从 0 开始的整数矩阵 grid ,矩阵大小为 m x n ,由从 0 到 m * n - 1 的不同整数组成。你可以…...
c 实用化的文本终端实时显示摄像头视频
因为采用yuv格式,帧率都很低。图像会拖影。把图像尺寸尽量缩小,能大大改善。现在最麻烦的是图像上有黑色的闪影,不知是为啥?如是framebuffer引起的就无解了。终于找到问题了,是在显示前加了一条用黑色清屏造成的&#…...
CSS中常用的伪类选择器
一 、伪类(不存在的类,特殊的类) -伪类用来描述一个元素的特殊状态 比如:第一个元素,被点击的元素,鼠标移入的元素 -特点:一般请情况下,使用:开头 1、 :first-child …...
【python学习】中级篇-数据库操作:SQLite
SQLite是一个轻量级的数据库引擎,它可以嵌入到各种应用程序中。以下是SQLite的基本用法: 创建数据库文件 import sqlite3# 连接到一个不存在的数据库文件,如果文件不存在,将会自动创建一个新的数据库文件 conn sqlite3.connect…...
汇编-PROTO声明过程
64位汇编 64 模式中,PROTO 伪指令指定程序的外部过程,示例如下: ExitProcess PROTO ;指定外部过程,不需要参数.code main PROCmov ebx, 0FFFFFFFFh mov ecx,0 ;结束程序call ExitProcess ;调用外部过程main ENDP END 32位…...
MYSQL事务操作
...
自动化测试——自动卸载软件
📢专注于分享软件测试干货内容,欢迎点赞 👍 收藏 ⭐留言 📝 如有错误敬请指正!📢交流讨论:欢迎加入我们一起学习!📢资源分享:耗时200小时精选的「软件测试」资…...
Linux - 系统调用(syscall)
说明 基于riscv64 soc linux_5.10.4平台,通过新增一个系统调用深入了解下系统调用实现原理。 简介 Linux 软件运行环境分为用户空间和内核空间,默认情况下,用户进程无法访问内核,既不能访问内核所在的内存空间,也不…...
c语言-冒泡排序
冒泡排序原理: 冒泡排序是一种简单直观的排序算法,它重复地遍历待排序的元素序列,比较相邻的两个元素,如果它们的顺序不符合要求(例如升序要求前面的元素小于后面的元素),则交换它们的位置。遍历…...
Mysql面经
Select语句的执行顺序 1、from 子句组装来自不同数据源的数据; 2、where 子句基于指定的条件对记录行进行筛选; 3、group by 子句将数据划分为多个分组; 4、使用聚集函数进行计算;AVG() SUM() MAX() MIN() COUNT() 5、使用 havin…...
1panel可视化Docker面板安装与使用
官网地址1Panel - 现代化、开源的 Linux 服务器运维管理面板 文章目录 目录 文章目录 前言 一、环境准备 二、使用步骤 1.安装命令 2.一些命令 3.使用 总结 前言 一、环境准备 虚拟机centos 已经安装好docker和 Docker Compose 或者都没安装 1panel会帮你自动安装 二、使用…...
es6中的import导入模块 和 export导出模块
es6中的import导入模块 和 export导出模块 一、定义二、使用1.默认导出导入2..命名导出导入3.命名导出(Named Export)与默认导出(Default Export)结合使用 三、总结 一、定义 功能:用于导入和导出模块的内容。 静态加载…...
WordPress插件开发教程手册 — 钩子(Hooks)
钩子是用一段代码添加/修改另外一段代码的方式,是 WordPress插件和主题与 WordPress 内核交互的基础,钩子在 WordPress 内核中也被广泛使用。WordPress 中有两种钩子,Action 和 Filter。使用钩子时,我们需要先编写一个自定义函数作…...
Python开发运维:Celery连接Redis
目录 一、理论 1.Celery 二、实验 1.Windows11安装Redis 2.Python3.8环境中配置Celery 3.celery的多目录结构异步执行 4.celery简单结构下的定时任务 三、问题 1.Celery命令报错 2.执行Celery命令报错 3.Win11启动Celery报ValueErro错误 4.Pycharm 无法 import 同目…...
JSP:JDBC
JDBC(Java Data Base Connectivity的缩写)是Java程序操作数据库的API,也是Java程序与数据库相交互的一门技术。 JDBC是Java操作数据库的规范,由一组用Java语言编写的类和接口组成,它对数据库的操作提供基本方法&#…...
CSS如何实现Less颜色函数自动计算渐变_使用lighten与darken实现视觉反馈
lighten() 和 darken() 按 HSL 的 L 分量线性调整亮度,非像素级明暗处理;需确保输入为 color 类型、慎用于高饱和色、避免链式调用,并配合 saturate 等增强视觉反馈。lighten() 和 darken() 在 Less 中怎么写才不翻车Less 的 lighten() 和 da…...
2026 多智能体全流程实战:用 Python + API 搭建可观测门店运营助手,附最小可复现代码
2026 多智能体全流程实战:用 Python API 搭建可观测门店运营助手,附最小可复现代码 从 2026-04-16 到 2026-04-18 的 6 条 AI 热点出发,拆到场景定义、关键代码、调试排错与上线建议 导语 先给最终效果:我们要做一个本地就能跑通…...
OpenMemories-Tweak终极指南:完全解锁索尼相机隐藏功能的完整教程
OpenMemories-Tweak终极指南:完全解锁索尼相机隐藏功能的完整教程 【免费下载链接】OpenMemories-Tweak Unlock your Sony cameras settings 项目地址: https://gitcode.com/gh_mirrors/op/OpenMemories-Tweak 你是否曾为索尼相机的30分钟录像限制感到困扰&a…...
从零构建你自己的CoreOS风格系统:使用rpm-ostree compose tree打造不可变基础设施镜像
从零构建CoreOS风格不可变系统:rpm-ostree全栈实践指南 当你在凌晨三点被生产环境突发的依赖冲突惊醒时,当容器集群因底层系统库版本不一致而集体崩溃时,不可变基础设施的理念便开始显现其价值。不同于传统Linux发行版中包管理器随意修改运行…...
如何用Nikto进行企业级Web安全评估?这些高级参数和技巧你必须知道
企业级Web安全评估实战:Nikto高级参数与深度防御策略 在数字化转型浪潮中,Web应用已成为企业核心业务的重要载体,但同时也是攻击者最常瞄准的目标。作为安全从业人员,我们需要像攻击者一样思考,却要以建设者的身份行动…...
从零上手nRF52840 DK:一次完整的开发环境配置与LED闪烁实战
1. 开发板开箱与基础认知 第一次拿到nRF52840 DK开发板时,我对着这个火柴盒大小的板子研究了半天。板子左上角那个显眼的4颗LED灯就是待会要征服的对象,右下角自带J-Link OB调试器意味着我们不需要额外购买烧录工具——这点对新手特别友好。板载的nRF528…...
手把手教你用PyTorch从零搭建并调优ConvNeXt图像分类模型
1. 环境准备与ConvNeXt初探 ConvNeXt是近年来备受关注的视觉模型,它用纯卷积结构达到了Transformer级别的性能。我第一次用它做花卉分类时,准确率比ResNet高了8个百分点。下面从最基础的环境搭建开始: 先创建Python3.8的conda环境ÿ…...
别再只会用cv2.threshold了!OpenCV图像二值化保姆级教程:从OTSU到Sauvola算法实战
OpenCV图像二值化实战:从基础阈值到Sauvola算法的深度解析 当处理一张光照不均的文档扫描件时,你是否遇到过这样的困境:使用简单的cv2.threshold后,要么文字断裂模糊,要么背景噪点泛滥?这就像用同一把钥匙想…...
watchfiles实战:如何构建企业级代码热重载系统
watchfiles实战:如何构建企业级代码热重载系统 【免费下载链接】watchfiles Simple, modern and fast file watching and code reload for Python, written in Rust 项目地址: https://gitcode.com/gh_mirrors/wa/watchfiles watchfiles是一个用Rust编写的现…...
3步快速修复:用G-Helper解决华硕笔记本屏幕色彩发白问题
3步快速修复:用G-Helper解决华硕笔记本屏幕色彩发白问题 【免费下载链接】g-helper Lightweight, open-source control tool for ASUS laptops and ROG Ally. Manage performance modes, fans, GPU, battery, and RGB lighting across Zephyrus, Flow, TUF, Strix, …...
