【JavaEE】多线程 -- 死锁问题

目录
1. 问题引入
2.死锁问题的概念和原因
3. 解决死锁问题
1. 问题引入
在学习死锁之前, 我们先观察下面的代码能否输出正确的结果:

运行程序, 能正常输出结果:

这个代码只管上看起来, 好像是有锁冲突的, 此时的 locker 对象已经是加锁的状态, 在尝试对 locker 加锁, 不应该会出现阻塞问题吗?
其实, 问题的关键是,这两次加锁, 其实是在同一个线程上进行的. 由于是同一个线程, 此时锁对象就知道了第二次加锁的线程, 第二次加锁操作就可以直接放行通过, 不会出现阻塞. 这个特性称为 "可重入".
使用可重入锁, 可以避免代码出现死锁问题, 如果使用的不是可重入锁, 就会出现死锁问题.
2.死锁问题的概念和原因
Java多线程中的死锁问题是指两个或多个线程互相持有对方所需的资源而无法继续执行的情况。这种情况下,线程无法释放已经占有的资源,也无法获取自己所需的资源,导致程序无法继续执行下去。
通常,发生死锁问题需要满足以下四个条件:
- 互斥条件(Mutual exclusion):至少有一个资源同时只能被一个线程占用。
- 请求与保持条件(Hold and wait):线程至少已经占有一个资源,并且正在请求另一个被其他线程占用的资源。
- 不可剥夺条件(No preemption):已经分配给一个线程的资源不能被强制剥夺。
- 循环等待条件(Circular wait):存在一个线程链,每个线程都在等待下一个线程所占有的资源。
死锁的例子:
线程1获取到锁A, 线程2获取到锁B, 接下来, 线程1尝试获取锁 B, 线程2尝试获取锁A, 此时出现了死锁问题:
package thread;public class ThreadDemo22 {public static void main(String[] args) {Object A = new Object();Object B = new Object();Thread t1 = new Thread(()-> {synchronized (A) {// sleep 是为了t2时间, 让t2也能拿到 Btry {Thread.sleep(1000);}catch (InterruptedException e) {e.printStackTrace();}//尝试获取B, 并没有释放 Asynchronized (B) {System.out.println("t1拿到了两把锁");}}});Thread t2 = new Thread(()->{synchronized (B) {// sleep 是给t1时间, 让t1能拿到 Atry {Thread.sleep(1000);}catch (InterruptedException e) {e.printStackTrace();}//尝试获取A, 并没有释放 Bsynchronized (A) {System.out.println("t2拿到了两把锁");}}});t1.start();t2.start();}
}
程序没有任何输出结果:
3. 解决死锁问题
为了避免死锁问题,可以采取以下策略:
- 避免使用多个锁:尽量减少使用多个锁,如果必须使用多个锁,确保获取锁的顺序是一致的,以减少死锁的可能性。
- 加锁顺序:多个线程获取锁的顺序要保持一致,避免出现循环等待条件。
- 加锁时限:在获取锁的时候设置超时时间,如果一段时间内没有获取到锁,就放弃当前的操作,释放已经持有的锁,避免长时间等待导致死锁。
- 死锁检测:通过监控线程的状态和资源的使用情况,及时检测并解决潜在的死锁问题。
对于死锁例子, 我们可以使两个线程的取锁顺序保持一致:
package thread;public class ThreadDemo22 {public static void main(String[] args) {Object A = new Object();Object B = new Object();Thread t1 = new Thread(()-> {synchronized (A) {// sleep 是为了t2时间, 让t2也能拿到 Btry {Thread.sleep(1000);}catch (InterruptedException e) {e.printStackTrace();}//尝试获取B, 并没有释放 Asynchronized (B) {System.out.println("t1拿到了两把锁");}}});Thread t2 = new Thread(()->{synchronized (A) {// sleep 是给t1时间, 让t1能拿到 Atry {Thread.sleep(1000);}catch (InterruptedException e) {e.printStackTrace();}//尝试获取A, 并没有释放 Bsynchronized (B) {System.out.println("t2拿到了两把锁");}}});t1.start();t2.start();}
}

相关文章:
【JavaEE】多线程 -- 死锁问题
目录 1. 问题引入 2.死锁问题的概念和原因 3. 解决死锁问题 1. 问题引入 在学习死锁之前, 我们先观察下面的代码能否输出正确的结果: 运行程序, 能正常输出结果: 这个代码只管上看起来, 好像是有锁冲突的, 此时的 locker 对象已经是加锁的状态, 在尝试对 locker 加锁, 不应该…...
XTU OJ 1339 Interprime 学习笔记
链接 传送门 代码 #include<bits/stdc.h> using namespace std;const int N1e610; //78498 我计算了一下,6个0的范围内有这么多个素数,所以开这么大的数组存素数 //计算的代码是一个循环 int prime[80000]; int a[N],s[N];//s数组是前缀和数组b…...
【Web安全】xss攻击方式与绕过
xss攻击方式与绕过 文章目录 xss攻击方式与绕过XSS攻击方式1. script标签2. img标签3. input标签4. details标签5. svg标签6. select标签7. iframe标签8. video标签9. audio标签10. body标签11. textarea标签 常见绕过方式1. 空格过滤2. 引号过滤3. 括号过滤4. 关键词过滤5. 编…...
文件夹重命名技巧:用关键词替换文件夹名称指定内容的右侧文字
在日常生活中,经常要管理大量的文件夹,这时候掌握一些文件夹重命名的技巧就非常实用。例如文件夹重命名时,经常要将一些通用的文字替换成其他关键词,以便更好地标识和分类文件夹。而用关键词替换文件夹名称指定内容的右侧文字&…...
python pip安装第三方包时报错 error: Microsoft Visual C++ 14.0 or greater is required.
文章目录 1.问题2.原因3.解决办法 1.问题 pip install 的时候报错一大堆,其中有这么一段话 👇 error: Microsoft Visual C 14.0 or greater is required. Get it with "Microsoft C Build Tools": https://visualstudio.microsoft.com/visua…...
对 .NET程序2G虚拟地址紧张崩溃 的最后一次反思
一:背景 1. 讲故事 最近接连遇到了几起 2G 虚拟地址紧张 导致的程序崩溃,基本上 90% 都集中在医疗行业,真的很无语,他们用的都是一些上古的 XP,Windows7 x86,我也知道技术人很难也基本无法推动硬件系统和…...
HCIA-RS基础-静态路由协议
摘要:静态路由是一种在网络中广泛应用的路由选择方案,它以其简单的配置和低开销而备受青睐。本文将介绍静态路由的配置方法、默认路由的设置、路由的负载分担和备份策略。通过学习本文,希望可以你能够掌握静态路由的基本概念和在华为模拟器中…...
LeetCode(46)汇总区间【区间】【简单】
目录 1.题目2.答案3.提交结果截图 链接: 汇总区间 1.题目 给定一个 无重复元素 的 有序 整数数组 nums 。 返回 恰好覆盖数组中所有数字 的 最小有序 区间范围列表 。也就是说,nums 的每个元素都恰好被某个区间范围所覆盖,并且不存在属于某…...
数据预处理:随机裁剪放缩
随机裁剪放缩是一种数据增强技术,可以在训练神经网络时增加数据的多样性,提高模型的泛化能力。具体来说,随机裁剪放缩可以通过随机裁剪和缩放原始图片来生成多个不同的训练样本,从而增加数据集的大小和多样性。这种技术在图像分类…...
RabbitMQ 搭建和工作模式
MQ基本概念 1. MQ概述 MQ全称 Message Queue([kjuː])(消息队列),是在消息的传输过程中保存消息的容器。多用于分布式系统之间进行通信。 (队列是一种容器,用于存放数据的都是容器࿰…...
一起学docker系列之七docker容器卷技术
目录 1 为什么使用容器数据卷?2 数据卷的特点和优势3 使用数据卷的方法3.1 创建容器并挂载数据卷3.2 容器间数据卷的共享与继承 4 数据卷的权限设置5 注意事项5.1 解决权限问题5.2 路径自动创建 结语 对于容器化应用程序的数据管理和持久化,Docker 数据卷…...
Loki安装部署
Loki安装部署 1、Loki介绍 Loki 是受 Prometheus 启发由 Grafana Labs 团队开源的水平可扩展,高度可用的多租户日志聚合系统。开发语 言: Google Go。它的设计具有很高的成本效益,并且易于操作。使用标签来作为索引,而不是对全文进行检索&…...
php如何实现文件上传
php实现文件上传需要通过全局变量(数组):$_FILES 结合 move_uploaded_file 函数来实现。 move_uploaded_file函数(只对POST方式生效): 其中move_uploaded_file函数语法:move_uploaded_file(需要…...
实验8配置工具
一、实验目的 1. 掌握UML中建模工具——部署图,用于显示系统中软件和硬件的物理架构。 2. 掌握应用Visio等业界常用的建模工具的基本使用方法和基本绘图操作,选择一种并熟练使用,会使用该工具针对具体问题建立分析模型。 二、实验内容与步骤…...
论文笔记:详解NEUPSL DSI
《Using Domain Knowledge to Guide Dialog Structure Induction via Neural Probabilistic 》 名词解释 Dialog Structure Induction(DSI)是推断给定目标导向对话的潜在对话结构(即一组对话状态及其时间转换)的任务。它是现代对…...
shared_ptr子类指针转换成父类指针
假设有如下应用场景: class Base { public:void addChild(std::shared_ptr<Base>& child){...} }class Derived : public Base {}int main() {Base a;std::shared_ptr<Derived> b std::make_shared<Derived>();a.addChild(b); // Error } 该代码中声…...
五、cookie、session、token、localstroage、sessionStroage区别
一、localStorage 跟 sessionStorage有什么不同???? localStorage 1、生命周期:localStorage的生命周期是永久的,关闭页面或浏览器之后localStorage中的数据也不会消失。localStorage除非主动删除数据&am…...
基于SpringBoot的在线视频教育平台的设计与实现
摘 要 随着科学技术的飞速发展,各行各业都在努力与现代先进技术接轨,通过科技手段提高自身的优势;对于在线视频教育平台当然也不能排除在外,随着网络技术的不断成熟,带动了在线视频教育平台,它彻底改变了过…...
Vue 2.0源码分析-渲染函数render
Vue 的 _render 方法是实例的一个私有方法,它用来把实例渲染成一个虚拟 Node。它的定义在 src/core/instance/render.js 文件中: Vue.prototype._render function (): VNode {const vm: Component thisconst { render, _parentVnode } vm.$options//…...
阿里云国际短信业务网络超时排障指南
选取一台或多台线上的应用服务器或选取相同网络环境下的机器,执行以下操作。 获取公网出口IP。 curl ifconfig.me 测试连通性。 (推荐)执行MTR命令(可能需要sudo权限),检测连通性,执行30秒。 m…...
DLSS Swapper终极指南:如何一键管理游戏DLSS版本提升50%性能
DLSS Swapper终极指南:如何一键管理游戏DLSS版本提升50%性能 【免费下载链接】dlss-swapper 项目地址: https://gitcode.com/GitHub_Trending/dl/dlss-swapper 你是否曾经因为游戏自带的DLSS版本过时而感到困扰?当最新的DLSS 3.5版本发布&#x…...
DouYinBot 抖音无水印视频解析工具:3分钟快速搭建个人解析服务
DouYinBot 抖音无水印视频解析工具:3分钟快速搭建个人解析服务 【免费下载链接】DouYinBot 该项目仅自用,不提供抖音视频下载 项目地址: https://gitcode.com/gh_mirrors/do/DouYinBot 在抖音内容创作日益普及的今天,如何快速获取无水…...
从零到专业:Sunshine虚拟手柄配置的5个关键突破点
从零到专业:Sunshine虚拟手柄配置的5个关键突破点 【免费下载链接】Sunshine Self-hosted game stream host for Moonlight. 项目地址: https://gitcode.com/GitHub_Trending/su/Sunshine 你是否曾在深夜准备享受游戏时,发现手柄在Sunshine串流中…...
可微分编程与强化学习在粒子探测器优化中的应用
1. 可微分编程在粒子探测器优化中的革新应用可微分编程(Differentiable Programming)正在彻底改变粒子探测器设计的传统范式。这种技术允许我们将整个探测器系统——从传感器几何形状到重建算法——构建为一个可微分的计算图。想象一下,这就像…...
机器学习加速格点QCD计算:从强子真空极化到重子质量修正
1. 项目概述:当格点QCD遇上机器学习在格点量子色动力学(Lattice QCD)的计算世界里,我们这些常年跟海量数据和超级计算机打交道的人,最头疼的问题之一就是“噪声”。这可不是实验室里嗡嗡响的那种声音,而是统…...
从Kaggle竞赛到业务落地:GBM特征重要性到底怎么看?用Python实战教你做模型可解释性分析
解密GBM特征重要性:从技术指标到业务决策的实战指南在金融风控和精准营销的实际业务场景中,数据科学家常常面临一个关键挑战:不仅要让模型预测准确,还要能够清晰解释模型决策的依据。GBM(Gradient Boosting Machines&a…...
ET框架:Unity游戏服务端的工业级架构实践
1. 这不是又一个“Unity做服务器”的噱头,而是把游戏服务端从“能跑”推进到“可维、可扩、可测”的分水岭“ET框架革命:Unity游戏服务器开发的终极解决方案”——这个标题里,“革命”二字不是修辞,是实打实的工程范式切换&#x…...
Autumn Valley资源包:开放世界性能优化实战指南
1. 这个资源包不是“拿来就能跑”的美术资产,而是为开放世界性能瓶颈量身定制的解决方案我第一次在Unity Asset Store看到Autumn Valley - Level这个包时,下意识点开预览图——金黄的枫林、雾气缭绕的山谷、蜿蜒的碎石小径,画面确实抓人。但真…...
Python数据库设计模式:从ORM到数据层架构
Python数据库设计模式:从ORM到数据层架构 引言 数据库设计是后端开发的核心环节。作为从Python转向Rust的后端开发者,我发现Python的数据库生态非常成熟,尤其是SQLAlchemy提供了强大的ORM能力。本文将深入探讨Python数据库设计模式࿰…...
深度揭秘:如何在Mac上无痛备份微信聊天记录
深度揭秘:如何在Mac上无痛备份微信聊天记录 【免费下载链接】WeChatExporter 一个可以快速导出、查看你的微信聊天记录的工具 项目地址: https://gitcode.com/gh_mirrors/wec/WeChatExporter 你是否曾因微信聊天记录丢失而懊恼?那些珍贵的对话、重…...
